const OSS = require('ali-oss') const router = require('@/router'); const Minio = require('minio') const stream = require('stream') import Vue from 'vue' import { customerHttp, OSSclose } from "@/utils/multipartUpload/oss" import { exist, AWSclose } from "@/utils/multipartUpload/aws" const { GetObjectStoreToken } = require('../api/user.js') const { S3Client, } = require("@aws-sdk/client-s3"); Vue.prototype.OSSclientConfig = { } async function ossGenerateSTS() { let res = null; if (localStorage.getItem('stsToken')) { res = JSON.parse(localStorage.getItem('stsToken')) } else { res = await GetObjectStoreToken() localStorage.setItem('stsToken', JSON.stringify(res)) } // res.Result.ObjectStoreUse = 'AWS'; Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] } Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse; Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint switch (res.Result.ObjectStoreUse) { case 'AliyunOSS': Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000 let OSSclient = new OSS(Vue.prototype.OSSclientConfig) Vue.prototype.OSSclient = { put: async function (objectName, object) { OSSclient = await RefreshClient(OSSclient) return new Promise(async (resolve, reject) => { try { let _vm = router.default.app if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { var objectItem = objectName.split('/') // objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1] objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring( 0, objectItem[objectItem.length - 1].lastIndexOf('.') )}__${new Date().getTime()}${objectItem[objectItem.length - 1].substring( objectItem[objectItem.length - 1].lastIndexOf('.') ).toLocaleLowerCase()}` objectName = objectItem.join('/') } let res = await OSSclient.put(objectName, object) if (res && res.url) { resolve({ name: objectName, url: res.url }) } else { reject() } } catch (e) { console.log(e) reject() } }) }, multipartUpload: async (data, progress) => { OSSclient = await RefreshClient(OSSclient) return new Promise(async (resolve, reject) => { try { const { file, path } = data; if (!file || !path) return reject('file and path be required'); let config = await getSTSToken(Vue.prototype.OSSclientConfig.expiration); if (config) { Vue.prototype.OSSclientConfig = { ...config.Result[config.Result.ObjectStoreUse] } Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse; Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint; Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000 OSSclient = new OSS(Vue.prototype.OSSclientConfig); } let _vm = router.default.app if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { var objectItem = data.path.split('/') // objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1] objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring( 0, objectItem[objectItem.length - 1].lastIndexOf('.') )}__${new Date().getTime()}${objectItem[objectItem.length - 1].substring( objectItem[objectItem.length - 1].lastIndexOf('.') ).toLocaleLowerCase()}` data.path = objectItem.join('/') } let res = await customerHttp(OSSclient, data, progress); if (res) { resolve({ name: data.path, url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(res.name) }) } else { reject() } } catch (err) { console.log(err) reject(err) } }) }, close: () => { OSSclose(); } } break case 'MinIO': let minioClient = new Minio.Client(Vue.prototype.OSSclientConfig); Vue.prototype.OSSclient = { put: function (objectName, object) { return new Promise(async (resolve, reject) => { try { var name = objectName.split('/')[objectName.split('/').length - 1] let _vm = router.default.app if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { var objectItem = objectName.split('/') objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1] objectName = objectItem.join('/') } const reader = new FileReader(); reader.onload = (ex) => { const bufferStream = new stream.PassThrough() bufferStream.end(Buffer.from(ex.target.result)) minioClient.putObject(Vue.prototype.OSSclientConfig.bucketName, objectName, bufferStream, function (err, etag) { if (err) { console.log(err) reject() } else { resolve({ name: objectName, url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(objectName) }) } }) }; reader.readAsArrayBuffer(object); } catch (e) { console.log(e) } }) }, close: () => { return false } } break case 'AWS': Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName let aws = new S3Client({ endpoint: Vue.prototype.OSSclientConfig.viewEndpoint, region: Vue.prototype.OSSclientConfig.region, s3ForcePathStyle: true, signatureVersion: 'v4', forcePathStyle: true, // SessionToken: '', credentials: { accessKeyId: Vue.prototype.OSSclientConfig.accessKeyId, secretAccessKey: Vue.prototype.OSSclientConfig.secretAccessKey, sessionToken: Vue.prototype.OSSclientConfig.sessionToken } }); Vue.prototype.OSSclient = { put: async function (objectName, object) { let data = { file: object, path: objectName } aws = await RefreshClient(aws); return uploadAWS(aws, data, () => { }); }, multipartUpload: async (data, progress) => { aws = await RefreshClient(aws); return uploadAWS(aws, data, progress); }, close: () => { AWSclose(); } } } return } // AWS上传函数 function uploadAWS(aws, data, progress) { return new Promise(async (resolve, reject) => { try { const { file, path } = data; if (!file || !path) return reject('file and path be required'); let _vm = router.default.app if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { var objectItem = data.path.split('/') // objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1] objectItem[objectItem.length - 1] = `${objectItem[objectItem.length - 1].substring( 0, objectItem[objectItem.length - 1].lastIndexOf('.') )}__${new Date().getTime()}${objectItem[objectItem.length - 1].substring( objectItem[objectItem.length - 1].lastIndexOf('.') ).toLocaleLowerCase()}` data.path = objectItem.join('/') } let bucketName = data.path.split("/")[1] || Vue.prototype.OSSclientConfig.bucket let curPath = data.path; data.path = data.path.replace(`/${bucketName}/`, ''); await exist(aws, bucketName, data, progress, (path, status) => { if (status === 'success') { resolve({ name: decodeUtf8(curPath), url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(curPath) }) } else { reject() } }); } catch (err) { console.log(err) reject(err) } }) } // client过期刷新 async function RefreshClient(client) { let config = await getSTSToken(Vue.prototype.OSSclientConfig.expiration); if (config) { // config.Result.ObjectStoreUse = 'AWS' switch (config.Result.ObjectStoreUse) { case 'AliyunOSS': { Vue.prototype.OSSclientConfig = { ...config.Result[config.Result.ObjectStoreUse] } Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse; Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint; Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000 return new OSS(Vue.prototype.OSSclientConfig); } case "MinIO": { return client; } case "AWS": { Vue.prototype.OSSclientConfig = { ...config.Result[config.Result.ObjectStoreUse] } Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse; Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint; Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName return new S3Client({ endpoint: Vue.prototype.OSSclientConfig.viewEndpoint, region: Vue.prototype.OSSclientConfig.region, s3ForcePathStyle: true, signatureVersion: 'v4', forcePathStyle: true, credentials: { accessKeyId: Vue.prototype.OSSclientConfig.accessKeyId, secretAccessKey: Vue.prototype.OSSclientConfig.secretAccessKey, sessionToken: Vue.prototype.OSSclientConfig.sessionToken } }); } } } else { return client; } } function decodeUtf8(bytes) { let str = bytes.split('?'); let str2 = str[0].split('/'); let name = str2[str2.length - 1]; name = encodeURIComponent(name); str.shift(); str2.pop(); return str2.join("/") + '/' + name; } const queue = [] let loading = false; // 获取凭证 function getSTSToken(credentials) { return new Promise(async (resolve, reject) => { let isExpired = isCredentialsExpired(credentials); if (isExpired) { if (loading) { queue.push({ resolve, reject }) } if (!loading) { loading = true; let res = await GetObjectStoreToken(); loading = false; localStorage.setItem('stsToken', JSON.stringify(res)) resolve(res) let p = queue.shift(); while (p) { p.resolve(res) p = queue.shift(); } } } else { // console.log("凭证未过期"); resolve(false) } }) } /** * oss判断临时凭证是否到期。 **/ function isCredentialsExpired(credentials) { if (!credentials) { return true; } const expireDate = new Date(credentials); const now = new Date(); // 如果有效期不足五分钟,视为过期。 return expireDate.getTime() - now.getTime() <= 300000; } export const OSSclient = ossGenerateSTS