chunkUpload.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { chunkUploadApi, mergeChunksApi } from '@/apis/upload';
  2. import calculateMD5 from './calculateMD5';
  3. interface Chunk {
  4. file: Blob;
  5. index: number;
  6. }
  7. interface UploadPartResponse {
  8. code?: number;
  9. message?: string;
  10. data?: any;
  11. }
  12. const CHUNK_SIZE = 5 * 1024 * 1024;
  13. export const chunkUpload = async (
  14. file: File, // 这里是 File 类型,包含文件名和类型信息
  15. onProgress?: (progress: number) => void
  16. ): Promise<string> => {
  17. const chunks: Chunk[] = [];
  18. const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
  19. const fileKey = await calculateMD5(file);
  20. // 创建分片
  21. for (let i = 0; i < totalChunks; i++) {
  22. const start = i * CHUNK_SIZE;
  23. const end = Math.min(start + CHUNK_SIZE, file.size);
  24. const chunk = file.slice(start, end);
  25. chunks.push({
  26. file: chunk,
  27. index: i + 1
  28. });
  29. }
  30. // 上传进度跟踪
  31. let uploadedChunks = 0;
  32. const uploadPromises = chunks.map(chunk => {
  33. return uploadChunk(
  34. chunk.file,
  35. fileKey,
  36. chunk.index,
  37. totalChunks,
  38. onProgress ? () => {
  39. uploadedChunks++;
  40. const progress = Math.round((uploadedChunks / totalChunks) * 100);
  41. console.log(`上传进度: ${progress}%`);
  42. onProgress(progress);
  43. } : undefined
  44. )
  45. })
  46. // 等待所有分片上传完成
  47. await Promise.all(uploadPromises)
  48. // 所有分片上传完成后,请求合并,传递文件名和类型
  49. await mergeChunksApi(
  50. fileKey,
  51. totalChunks,
  52. file.name,
  53. file.type
  54. );
  55. return fileKey;
  56. };
  57. const uploadChunk = async (
  58. chunk: Blob,
  59. fileKey: string,
  60. chunkNumber: number,
  61. totalChunks: number,
  62. onProgress?: () => void
  63. ): Promise<UploadPartResponse> => {
  64. const formData = new FormData();
  65. formData.append('file', chunk);
  66. formData.append('fileKey', fileKey);
  67. formData.append('chunkNumber', chunkNumber.toString());
  68. formData.append('totalChunks', totalChunks.toString());
  69. try {
  70. const response = await chunkUploadApi(formData)
  71. if (onProgress) {
  72. onProgress();
  73. }
  74. return { message: response.data.message || '上传成功' };
  75. } catch (error: any) {
  76. console.error(`分片 ${chunkNumber} 上传失败:`, error);
  77. throw error;
  78. }
  79. }