325 lines
12 KiB
JavaScript
325 lines
12 KiB
JavaScript
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
|