大规格文件的上传优化思路详解
上传完所有文件分片后,前端主动通知服务端进行合并,服务端接受到这个请求时主动合并切片,通过文件 MD5 在服务器的文件上传路径中找到同名文件夹。从上文可知,文件分片是按照分片序号命名的,而分片上传接口是异步的,无法保证服务器接收到的切片是按照请求顺序拼接。所以应该在合并文件夹里的分片文件前,根据文件名进行排序,然后再通过 concat-files 合并分片文件,得到用户上传的文件。至此大文件上传就完成了。 Node 端代码: // 合并文件 exports.merge = { validate: { query: { fileName: Joi.string() .trim() .required() .description('文件名称'), md5: Joi.string() .trim() .required() .description('文件md5'), size: Joi.string() .trim() .required() .description('文件大小'), }, }, permission: { roles: ['user'], }, async handler (ctx) { const { fileName, md5, size } = ctx.request.query let { name, base: filename, ext } = path.parse(fileName) const newFileName = randomFilename(name, ext) await mergeFiles(path.join(uploadDir, md5), uploadDir, newFileName, size) .then(async () => { const file = { key: newFileName, name: filename, mime_type: mime.getType(`${uploadDir}/${newFileName}`), ext, path: `${uploadDir}/${newFileName}`, provider: 'oss', size, owner: ctx.state.user.id, } const key = encodeURIComponent(file.key) .replace(/%/g, '') .slice(-100) file.url = await uploadLocalFileToOss(file.path, key) file.url = getFileUrl(file) const f = await File.create(omit(file, 'path')) const files = [] files.push(f) ctx.body = invokeMap(files, 'toJSON') }) .catch(() => { throw Boom.badData('大文件分片合并失败,请稍候重试~') }) }, } 总结 本文讲述了大规格文件上传优化的一些做法,总结为以下 4 点: ob.slice 将文件切片,并发上传多个切片,所有切片上传后告知服务器合并,实现大文件分片上传; 原生 XMLHttpRequest 的 onprogress 对切片上传进度的监听,实时获取文件上传进度; spark-md5 根据文件内容算出文件 MD5,得到文件唯一标识,与文件上传状态绑定; 分片上传前通过文件 MD5 查询已上传切片列表,上传时只上传未上传过的切片,实现断点续传。 参照 Demo 源码 可快速上手上述功能 到此这篇关于大规格文件的上传优化思路详解的文章就介绍到这了,更多相关大文件上传优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! (编辑:衡阳站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |