福州网站建站建设wordpress左侧目录主题
- 作者: 五速梦信息网
- 时间: 2026年03月21日 11:14
当前位置: 首页 > news >正文
福州网站建站建设,wordpress左侧目录主题,网易网,昆明大型网站建设文件上传是常见需求#xff0c;只要指定 content-type 为 multipart/form-data#xff0c;内容就会以这种格式被传递到服务端#xff1a; 服务端再按照 multipart/form-data 的格式提取数据#xff0c;就能拿到其中的文件。 但当文件很大的时候#xff0c;事情就变得不一样…文件上传是常见需求只要指定 content-type 为 multipart/form-data内容就会以这种格式被传递到服务端 服务端再按照 multipart/form-data 的格式提取数据就能拿到其中的文件。 但当文件很大的时候事情就变得不一样了。 假设传一个 100M 的文件需要 3 分钟那传一个 1G 的文件就需要 30 分钟。 这样是能完成功能但是产品的体验会很不好。 所以大文件上传的场景需要做专门的优化。 把 1G 的大文件分割成 10 个 100M 的小文件然后这些文件并行上传不就快了 然后等 10 个小文件都传完之后再发一个请求把这 10 个小文件合并成原来的大文件。 这就是大文件分片上传的方案。 那如何拆分和合并呢 浏览器里 Blob 有 slice 方法可以截取某个范围的数据而 File 就是一种 Blob 所以可以在 input 里选择了 file 之后通过 slice 对 File 分片。 那合并呢 fs 的 createWriteStream 方法支持指定 start也就是从什么位置开始写入。 这样把每个分片按照不同位置写入文件里不就完成合并了么。 思路理清了接下来我们实现一下。 创建个 Nest 项目 npm install -g nestjs/clinest new large-file-sharding-upload在 AppController 添加一个路由 Post(upload) UseInterceptors(FilesInterceptor(files, 20, {dest: uploads })) uploadFiles(UploadedFiles() files: ArrayExpress.Multer.File, Body() body) {console.log(body, body);console.log(files, files); }这是一个 post 接口会读取请求体里的 files 文件字段传入该方法。 这里还需要安装用到的 multer 包的类型 npm install -D types/multer然后我们在网页里试一下 首先在 main.ts 里开启跨域支持 然后添加一个 index.html !DOCTYPE html html langen headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlescript srchttps://unpkg.com/axios0.24.0/dist/axios.min.js/script /head bodyinput idfileInput typefile multiple/scriptconst fileInput document.querySelector(#fileInput);fileInput.onchange async function () {const data new FormData();data.set(name,光);data.set(age, 20);[…fileInput.files].forEach(item {data.append(files, item)})const res await axios.post(http://localhost:3000/upload, data);console.log(res);}/script /body /htmlinput 指定 multiple可以选择多个文件。 选择文件之后通过 post 请求 upload 接口携带 FormData。FormData 里保存着 files 和其它字段。 起个静态服务 npx http-server .浏览器访问下 选择几个文件 这时候Nest 服务端就接收到了上传的文件和其他字段 当然我们并不是想上传多个文件而是一个大文件的多个分片。 所以是这样写 !DOCTYPE html html langen headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlescript srchttps://unpkg.com/axios0.24.0/dist/axios.min.js/script /head bodyinput idfileInput typefile/scriptconst fileInput document.querySelector(#fileInput);const chunkSize 20 * 1024;fileInput.onchange async function () {const file fileInput.files[0];console.log(file);const chunks [];let startPos 0;while(startPos file.size) {chunks.push(file.slice(startPos, startPos chunkSize));startPos chunkSize;}chunks.map((chunk, index) {const data new FormData();data.set(name, file.name - index)data.append(files, chunk);axios.post(http://localhost:3000/upload, data);})}/script /body /html对拿到的文件进行分片然后单独上传每个分片分片名字为文件名 index。 这里我们测试用的图片是 80k 所以每 20k 一个分片一共是 4 个分片。 测试下 服务端接收到了这 4 个分片: 然后我们把它们移动到单独的目录 Post(upload) UseInterceptors(FilesInterceptor(files, 20, {dest: uploads })) uploadFiles(UploadedFiles() files: ArrayExpress.Multer.File, Body() body: { name: string }) {console.log(body, body);console.log(files, files);const fileName body.name.match(/(.)-\d$/)[1];const chunkDir uploads/chunks_ fileName;if(!fs.existsSync(chunkDir)){fs.mkdirSync(chunkDir);}fs.cpSync(files[0].path, chunkDir / body.name);fs.rmSync(files[0].path); }用正则匹配出文件名 在 uploads 下创建 chunks_文件名 的目录把文件复制过去然后删掉原始文件。 测试下 分片文件移动成功了。 不过直接以 chunks文件名 做为目录名太容易冲突了。 我们可以在上传文件的时候给文件名加一个随机的字符串。 这样就不会冲突了 接下来就是在全部分片上传完之后发送合并分片的请求。 添加一个 merge 的接口 Get(merge) merge(Query(name) name: string) {const chunkDir uploads/chunks name;const files fs.readdirSync(chunkDir);let startPos 0;files.map(file {const filePath chunkDir / file;const stream fs.createReadStream(filePath);stream.pipe(fs.createWriteStream(uploads/ name, {start: startPos}))startPos fs.statSync(filePath).size;}) }接收文件名然后查找对应的 chunks 目录把下面的文件读取出来按照不同的 start 位置写入到同一个文件里。 浏览器访问下这个接口 可以看到合并成功了 再测试一个 也没啥问题。 然后我们在合并完成之后把 chunks 目录删掉。 Get(merge) merge(Query(name) name: string) {const chunkDir uploads/chunks_ name;const files fs.readdirSync(chunkDir);let count 0;let startPos 0;files.map(file {const filePath chunkDir / file;const stream fs.createReadStream(filePath);stream.pipe(fs.createWriteStream(uploads/ name, {start: startPos})).on(finish, () {count ;if(count files.length) {fs.rm(chunkDir, {recursive: true}, () {});}})startPos fs.statSync(filePath).size;}); }然后在前端代码里当分片全部上传完之后调用 merge 接口 const tasks []; chunks.map((chunk, index) {const data new FormData();data.set(name, randomStr _ file.name - index)data.append(files, chunk);tasks.push(axios.post(http://localhost:3000/upload, data)); }) await Promise.all(tasks); axios.get(http://localhost:3000/merge?name randomStr _ file.name);连起来测试下 因为文件比较小开启 network 的 slow 3g 网速来测。 可以看到分片上传和最后的合并都没问题。 当然你还可以加一个进度条这个用 axios 很容易实现 至此大文件分片上传就完成了。 总结 当文件比较大的时候文件上传会很慢这时候一般我们会通过分片的方式来优化。 原理就是浏览器里通过 slice 来把文件分成多个分片并发上传。 服务端把这些分片文件保存在一个目录下。 当所有分片传输完成时发送一个合并请求服务端通过 fs.createWriteStream 指定 start 位置来把这些分片文件写入到同一个文件里完成合并。 这样我们就实现了大文件分片上传。 Nest 实现大文件分片上传 原文链接https://juejin.cn/post/7315591545741197349
- 上一篇: 福州网站建设专业定制公众号开发微商城
- 下一篇: 福州网站开发培训华强北网站建设公司
相关文章
-
福州网站建设专业定制公众号开发微商城
福州网站建设专业定制公众号开发微商城
- 技术栈
- 2026年03月21日
-
福州网站建设找百诚互联微信朋友圈怎么投放广告
福州网站建设找百诚互联微信朋友圈怎么投放广告
- 技术栈
- 2026年03月21日
-
福州网站建设设计公司建设网站需要多少钱济南兴田德润o地址
福州网站建设设计公司建设网站需要多少钱济南兴田德润o地址
- 技术栈
- 2026年03月21日
-
福州网站开发培训华强北网站建设公司
福州网站开发培训华强北网站建设公司
- 技术栈
- 2026年03月21日
-
福州网站平台建设公司北京做企业网站多少钱
福州网站平台建设公司北京做企业网站多少钱
- 技术栈
- 2026年03月21日
-
福州网站设计软件公司wordpress登陆后跳转页面
福州网站设计软件公司wordpress登陆后跳转页面
- 技术栈
- 2026年03月21日






