Commit d38924f0 by renmanyi

feat:分片上传兼容腾讯云

parent bfbbdaaf
......@@ -21,7 +21,8 @@
"@types/underscore": "^1.10.22",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"ali-oss": "6.17.1",
"ali-oss": "^6.23.0",
"cos-js-sdk-v5": "^1.10.1",
"antd": "^4.16.3",
"array-move": "^3.0.1",
"axios": "^0.20.0",
......
......@@ -9,6 +9,7 @@ import {
FILR_VERIFY_MAP,
UPLOAD_PART_SIZE,
UPLOAD_PARALLEL,
TX_UPLOAD_REGION,
} from "@/domains/resource-disk/constants";
import { getFileTypeByName } from '@/domains/resource-disk/utils';
import UploadFileService from '@/domains/resource-disk/UploadFileService';
......@@ -72,15 +73,17 @@ class UploadProgressModal extends React.Component {
accessTypeEnum: 'PUBLIC',
bizCode: 'UPLOAD_FOLDER',
}).then((result) => {
const { ossClient, resourceId, callBack, callbackBody, ossUri } = result;
this.setState({
ossClient,
resourceId,
callBack,
callbackBody,
ossUri
});
resolve({ ossClient, resourceId, callBack, callbackBody, ossUri });
const { ossClient, resourceId, ossUri, vendorType,bucket,callbackData,callback} = result;
this.setState({
ossClient,
resourceId,
callbackData,
callback,
ossUri,
bucket,
vendorType
});
resolve({ ossClient, resourceId, vendorType, bucket, callbackData, callback, ossUri });
})
})
}
......@@ -97,29 +100,62 @@ class UploadProgressModal extends React.Component {
// 开始上传之前初始化OssClient
this.initOssClient(id, resourceName).then((result) => {
const { ossClient, resourceId, callBack, callbackBody, ossUri } = result;
ossClient.multipartUpload(ossUri, fileContent, {
callback: {
url: callBack,
body: callbackBody,
contentType: 'application/json',
},
parallel: UPLOAD_PARALLEL,
partSize: UPLOAD_PART_SIZE,
progress: (progress, checkpoint) => {
this.onMultipartUploadProgress(progress, checkpoint, file)
},
mime: type
}).then(url => {
console.log('1111');
file.status = 'success';
this.setState({ fileList });
this.props.onUpload(fileContent, resourceId);
}).catch(err => {
file.status = 'fail';
this.setState({ fileList });
});
const { ossClient, resourceId, ossUri, vendorType,bucket,callbackData,callback} = result;
if (vendorType === 'TENCENT_COS') {
// 腾讯云分片上传
ossClient.sliceUploadFile({
Bucket: bucket,
Region: TX_UPLOAD_REGION,
Key:ossUri,
Body: fileContent,
SliceSize: UPLOAD_PART_SIZE,
// 回调配置
Callback: callback,
onProgress: (progressData) => {
const progress = progressData.percent;
this.onMultipartUploadProgress(progress, { uploadId: randomString(16), file: fileContent }, file);
},
onTaskReady: (taskId) => {
// 记录任务ID,用于取消上传
file.taskId = taskId;
},
})
.then(res => {
file.status = 'success';
this.setState({ fileList });
this.props.onUpload(fileContent, resourceId);
})
.catch(err => {
file.status = 'fail';
this.setState({ fileList });
});
} else {
// 阿里云分片上传
ossClient
.multipartUpload(ossUri, fileContent, {
callback: {
url: callbackData.url,
body: callbackData.body,
callbackSNI: true,
contentType: callbackData.contentType
},
parallel: UPLOAD_PARALLEL,
partSize: UPLOAD_PART_SIZE,
progress: (progress, checkpoint) => {
this.onMultipartUploadProgress(progress, checkpoint, file);
},
mime: type
})
.then(url => {
file.status = 'success';
this.setState({ fileList });
this.props.onUpload(fileContent, resourceId);
})
.catch(err => {
file.status = 'fail';
this.setState({ fileList });
});
}
});
}
......@@ -133,42 +169,79 @@ class UploadProgressModal extends React.Component {
// 如果文件小于100KB,不用记录断点,直接上传
const { fileContent } = file;
const { size } = fileContent;
if (size > 100 * 1024) {
if (size > 100 * 1024 && checkpoint && checkpoint.uploadId) {
// 确保checkpoint和uploadId存在时才记录
if (!file.checkpoints) {
file.checkpoints = {};
}
file.checkpoints[checkpoint.uploadId] = checkpoint;
}
}
// 断点续传
handleReUpload = (index) => {
const { fileList, ossClient, resourceId, callBack, callbackBody } = this.state;
const { fileList, bucket,ossUri, ossClient, callback, resourceId, callbackData, vendorType } = this.state;
const currentFile = fileList[index];
const { checkpoints, fileContent } = currentFile
Object.values(checkpoints).forEach(checkpoint => {
const { uploadId, file } = checkpoint;
const { type } = file;
ossClient.multipartUpload(uploadId, file, {
callback: {
url: callBack,
body: callbackBody,
contentType: 'application/json',
const { checkpoints, fileContent } = currentFile;
if ( vendorType === 'TENCENT_COS') {
// 腾讯云重新上传
ossClient.sliceUploadFile({
Bucket: bucket,
Region: TX_UPLOAD_REGION,
Key: ossUri,
Body: fileContent,
SliceSize: UPLOAD_PART_SIZE,
// 回调配置
Callback: callback,
onProgress: (progressData) => {
const progress = progressData.percent;
this.onMultipartUploadProgress(progress, { uploadId: uuid(), file: fileContent }, currentFile);
},
checkpoint,
parallel: UPLOAD_PARALLEL,
partSize: UPLOAD_PART_SIZE,
progress: (progress, checkpoint) => {
this.onMultipartUploadProgress(progress, checkpoint, currentFile)
onTaskReady: (taskId) => {
currentFile.taskId = taskId;
},
mime: type,
}).then(url => {
currentFile.status = 'success';
this.setState({ fileList });
this.props.onUpload(fileContent, resourceId);
}).catch(err => {
currentFile.status = 'fail';
this.setState({ fileList });
})
.then(res => {
currentFile.status = 'success';
this.setState({ fileList });
this.props.onUpload(fileContent, resourceId);
})
.catch(err => {
currentFile.status = 'fail';
this.setState({ fileList });
});
} else {
Object.values(checkpoints).forEach(checkpoint => {
const { uploadId, file } = checkpoint;
const { type } = file;
ossClient
.multipartUpload(uploadId, file, {
callback: {
url: callbackData.url,
body: callbackData.body,
callbackSNI: true,
contentType: callbackData.contentType
},
checkpoint,
parallel: UPLOAD_PARALLEL,
partSize: UPLOAD_PART_SIZE,
progress: (progress, checkpoint) => {
this.onMultipartUploadProgress(progress, checkpoint, currentFile);
},
mime: type
})
.then(url => {
currentFile.status = 'success';
this.setState({ fileList });
this.props.onUpload(fileContent, resourceId);
})
.catch(err => {
currentFile.status = 'fail';
this.setState({ fileList });
});
});
})
}
}
// 显示/隐藏上传进度
......@@ -181,7 +254,7 @@ class UploadProgressModal extends React.Component {
// 取消上传
handleCancelAllUpload = () => {
// 判断是否有正在上传或者待上传的文件,有的话弹出二次提示框
const { fileList, ossClient } = this.state;
const { fileList, ossClient, vendorType } = this.state;
const uploadingFileList = fileList.filter(file => file.status === 'uploading' || file.status === 'waiting');
if (uploadingFileList.length) {
Modal.confirm({
......@@ -190,11 +263,19 @@ class UploadProgressModal extends React.Component {
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
onOk: () => {
uploadingFileList.forEach((uploadingFile, index) => {
const { checkpoints } = uploadingFile;
Object.values(checkpoints).forEach(checkpoint => {
const { uploadId, name } = checkpoint;
ossClient.abortMultipartUpload(name, uploadId);
});
if (vendorType === 'TENCENT_COS') {
// 腾讯云取消上传
if (uploadingFile.taskId) {
ossClient.cancelTask(uploadingFile.taskId);
}
} else {
// 阿里云取消上传
const { checkpoints } = uploadingFile;
Object.values(checkpoints).forEach(checkpoint => {
const { uploadId, name } = checkpoint;
ossClient.abortMultipartUpload(name, uploadId);
});
}
fileList.splice(index, 1);
});
this.setState({ fileList: [] });
......@@ -209,15 +290,20 @@ class UploadProgressModal extends React.Component {
// 取消单个文件上传
handleCancelUpload = (currentFile, index) => {
const { fileList, ossClient } = this.state;
const { checkpoints } = currentFile;
Object.values(checkpoints).forEach(checkpoint => {
const { uploadId, name } = checkpoint;
ossClient.abortMultipartUpload(name, uploadId);
});
const { fileList, ossClient, vendorType } = this.state;
if (vendorType === 'TENCENT_COS') {
// 腾讯云取消上传
if (currentFile.taskId) {
ossClient.cancelTask(currentFile.taskId);
}
} else {
// 阿里云取消上传
const { checkpoints } = currentFile;
Object.values(checkpoints).forEach(checkpoint => {
const { uploadId, name } = checkpoint;
ossClient.abortMultipartUpload(name, uploadId);
});
}
fileList.splice(index, 1);
this.setState({ fileList });
......
/*
* @Author: 吴文洁
* @Date: 2020-08-31 09:34:51
* @LastEditors: wufan
* @LastEditTime: 2021-01-06 20:18:46
* @LastEditors: renmanyi
* @LastEditTime: 2026-02-03 15:29:54
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -34,10 +34,7 @@ class Service {
static get(url: string, params: any, option?: any) {
return Axios.post('GET', url, params, option);
}
static MFS(url: string, params: any, option: any) {
return Axios.post('POST', `mfs/${url}`, params, option);
}
}
export default Service;
\ No newline at end of file
/*
* @Author: wufan
* @Date: 2020-12-01 17:21:21
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-07-09 15:33:33
* @LastEditors: renmanyi
* @LastEditTime: 2026-02-03 15:38:02
* @Description: Description
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -72,11 +72,12 @@ export const getOssClient = (
resourceName: string,
accessTypeEnum: string
) => {
return Service.postJSON('mfs/anon/mfs/multiPartUpload', {
return Service.postJSON('business/public/mfs/commonUpload', {
data,
instId,
bizCode,
resourceName,
needSecret: true,
accessTypeEnum
});
}
......
/*
* @Author: 吴文洁
* @Date: 2020-10-10 18:21:47
* @LastEditors: wufan
* @LastEditTime: 2020-12-09 16:05:24
* @LastEditors: renmanyi
* @LastEditTime: 2026-02-03 15:38:06
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -15,11 +15,12 @@ export const getOssClient = (
resourceName: string,
accessTypeEnum: string
) => {
return Service.postJSON('mfs/anon/mfs/multiPartUpload', {
return Service.postJSON('business/public/mfs/commonUpload', {
data,
instId,
bizCode,
resourceName,
needSecret: true,
accessTypeEnum
});
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2020-10-10 18:19:34
* @LastEditors: 吴文洁
* @LastEditTime: 2020-10-13 18:09:39
* @LastEditors: renmanyi
* @LastEditTime: 2026-02-03 15:39:33
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import OSS from 'ali-oss';
import COS from 'cos-js-sdk-v5';
import { UPLOAD_REGION } from '@/domains/resource-disk/constants';
import { getOssClient } from '@/data-source/basic/basic-apis';
......@@ -31,32 +32,26 @@ export default class UploadFileService {
accessTypeEnum
).then((res) => {
const { result = {} } = res;
const {
bucket,
callBack,
resourceId,
accessKeyId,
securityToken,
accessKeySecret,
callbackBody,
ossUri
} = result;
const ossClient = new OSS({
bucket,
accessKeyId,
accessKeySecret,
region: UPLOAD_REGION,
stsToken: securityToken,
});
resolve({
ossClient,
resourceId,
callBack,
callbackBody,
ossUri
});
const { bucket, resourceId, accessKeyId, securityToken, accessKeySecret, key, vendorType, callbackData, callback } = result;
let client;
if (vendorType === 'TENCENT_COS') {
// 腾讯云配置
client = new COS({
SecretId: accessKeyId,
SecretKey: accessKeySecret,
SecurityToken: securityToken
});
} else {
// 阿里云配置
client = new OSS({
bucket,
accessKeyId,
accessKeySecret,
region: UPLOAD_REGION,
stsToken: securityToken
});
}
resolve({ ossClient: client, resourceId, ossUri:key, vendorType,bucket,callbackData,callback });
})
})
}
......
/*
* @Author: 吴文洁
* @Date: 2020-08-20 09:21:40
* @LastEditors: yuananting
* @LastEditTime: 2021-07-15 11:48:58
* @LastEditors: renmanyi
* @LastEditTime: 2026-02-03 15:45:43
* @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -172,6 +172,7 @@ const NON_COMPLIANT_FILE_MAP = {
// 文件上传
const UPLOAD_REGION = 'oss-cn-hangzhou';
const TX_UPLOAD_REGION = 'ap-shanghai';
const UPLOAD_PART_SIZE = 1024 * 1024; // 每个分片大小(byte)
const UPLOAD_PARALLEL = 5; // 同时上传的分片数
......@@ -185,6 +186,7 @@ export {
DISK_MAP,
SUFFIX_MAP,
UPLOAD_REGION,
TX_UPLOAD_REGION,
UPLOAD_PART_SIZE,
UPLOAD_PARALLEL,
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment