赞
踩
大文件上传的文件切片逻辑, 包括如何将分片文件上传到本地服务器, 请查看之前的文章: 前端大文件上传 - 总结(Vue3 + hook + Web Worker实现,通过多个Worker线程大大提高Hash计算的速度), 本篇仅实现如何将大文件分块上传到S3.
后面写一篇文章实现选中多个文件,显示上传列表可取消上传,以及整合这两篇文件到一篇里,因为涉及的逻辑比较多
上节的代码实现中的 uploadFile 函数,我们只需要在对应的代码中添加 加粗样式就行
// 例如下面 async function uploadFile() { const data = await checkFile() if (!data) return const { chunk_upload, upload_id } = data uploadId.value = upload_id if (chunk_upload.length === 0) { // 上传整个文件 // 上传到S3 if (isS3) return await handleUploadS3Request() } if (chunk_upload.length !== chunkTotal.value) { // 上传未上传的分片 - 断点续传 if (isS3) return await handleUploadS3Request(chunk_upload) } // 无论是上传到S3还是本地服务器可能存在合并失败的问题 // 这里应该处理未合并的情况,值需要发送合并请求 code... // 上传完成 - 秒传(可能需要发起合并请求) code... }
提醒: 获取ETag需要配置对应的桶策略,ExposeHeaders数组里配置ETag。
// 记录上传到S3的分块 const s3UploadedChunks = ref([]) // 上传到S3 async function handleUploadS3Request(uploadedChunks = []) { s3UploadedChunks.value = JSON.parse(JSON.stringify(uploadedChunks)) for (let i = 0; i < fileChunkList.value.length; i++) { if (uploadedChunks.indexOf(i + 1) === -1) { // 申请上传S3的url const { code, data, msg } = await applyS3UrlFn({ part_no: i + 1, upload_id: uploadId.value, }) if (code === 0) { try { await uploadS3Chunk(data.signed_url, i) } catch (error) { // 上传失败 ... return false } } else { // 申请失败 ... return false } } } } // 上传S3文件某个分块 async function uploadS3Chunk(url, i) { const etag = await createXhr(url, i) // 记录已上传的分块 s3UploadedChunks.value.push(i + 1) // 上传S3文件某个分块完成 await s3ChunkDoneFn({ part_no: i + 1, upload_id: uploadId.value, etag, }) if (s3UploadedChunks.value.length === chunkTotal.value) { // 上传S3文件所有分块完成 await s3AllChunkDoneFn({ upload_id: uploadId.value }) // 上传成功 callback && callback() } } let xhr = null // 使用XMLHttpRequest上传Chunk async function createXhr(url, i) { return new Promise((resolve, reject) => { xhr = new XMLHttpRequest() xhr.open('PUT', url) xhr.upload.onprogress = (e) => { getFileProgress(e, i) } xhr.onload = () => { if (xhr.status === 200) { // 返回ETag resolve(xhr.getResponseHeader('ETag')) } else { reject(new Error('File upload failed')) } } xhr.onerror = () => { reject(new Error('File upload failed')) } xhr.onabort = () => { cancelFn({ upload_id: uploadId.value }) reject(new Error('File upload aborted')) } xhr.send(fileChunkList.value[i]) }) }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。