工作中如何实现大文件的上传?

问题背景

在 Web 开发中,上传大文件是一个常见的需求。然而,由于 HTTP 协议的限制和网络环境的不稳定性,直接将大文件一次性上传到服务器可能会导致性能问题或者上传失败。因此,需要采用一些特殊的技术和策略来实现高效的大文件上传。

解决方案

一种常用的解决方案是将大文件分片(Chunk)上传。即将大文件拆分为多个较小的块,然后逐个上传这些块。在服务器端,接收到这些块后再进行合并,最终得到完整的文件。

前置知识

在实现大文件上传之前,你需要了解以下几个概念和技术:

• 文件分片: 将大文件分割成多个较小的块(chunk),每个块的大小通常在几百 KB 到几 MB 之间。

• 文件元数据: 除了文件内容,还需要传输文件的元数据,如文件名、文件类型等。

• 文件上传进度: 为了提供更好的用户体验,应该能够实时显示上传进度。

• 服务器端处理: 服务器需要接收和处理每个分片,并在所有分片上传完毕后进行合并操作。

代码示例

以下是一个使用 JavaScript 和 Node.js 实现大文件分片上传的示例:

前端代码(使用 Axios 发送分片请求)

js 复制代码
const CHUNK_SIZE = 5 * 1024 * 1024; // 每个分片的大小(这里设置为5MB)  
  
async function uploadFile(file) {  
  const totalChunks = Math.ceil(file.size / CHUNK_SIZE);  
    
  for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {  
    const start = chunkIndex * CHUNK_SIZE;  
    const end = Math.min(start + CHUNK_SIZE, file.size);  
    const chunk = file.slice(start, end);  
      
    const formData = new FormData();  
    formData.append('file', chunk);  
    formData.append('chunkIndex', chunkIndex);  
    formData.append('totalChunks', totalChunks);  
      
    await axios.post('/upload', formData, {  
      headers: {  
        'Content-Type': 'multipart/form-data'  
      },  
      onUploadProgress: progressEvent => {  
        const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);  
        console.log(`Chunk ${chunkIndex + 1}/${totalChunks} uploaded: ${progress}%`);  
      }  
    });  
  }  
}

后端代码(使用 Express 处理分片上传)

js 复制代码
// 后端代码(使用 Express 处理分片上传)  
  
const fs = require('fs');  
const path = require('path');  
const express = require('express');  
const multer = require('multer');  
  
const app = express();  
const upload = multer({ dest: 'uploads/' });  
  
app.post('/upload', upload.single('file'), (req, res) => {  
  const { file, body: { chunkIndex, totalChunks } } = req;  
  const filePath = path.join('uploads/', file.originalname + '-' + chunkIndex);  
    
  fs.renameSync(file.path, filePath);  
    
  if (parseInt(chunkIndex, 10) === parseInt(totalChunks, 10) - 1) {  
    // 最后一个分片上传完成,进行合并操作  
    const writeStream = fs.createWriteStream(path.join('uploads/', file.originalname));  
      
    for (let i = 0; i < totalChunks; i++) {  
      const chunkPath = path.join('uploads/', file.originalname + '-' + i);  
      const chunk = fs.readFileSync(chunkPath);  
      fs.unlinkSync(chunkPath);  
      writeStream.write(chunk);  
    }  
      
    writeStream.end();  
  }  
    
  res.sendStatus(200);  
});  
  
app.listen(3000, () => {  
  console.log('Server started on port 3000');  
});

在上面的示例中,前端使用 Axios 库发送分片请求,后端使用 Express 框架和 Multer 中间件处理分片上传。前端代码会将大文件切割成多个块并逐个上传,同时显示上传进度。后端在接收到每个分片后,将其保存在服务器上,并在最后一个分片上传完成后进行合并操作。

总结

总的来说,大文件上传的关键是将大文件分片上传,以提高性能和稳定性。这种分片上传的方法适用于各种类型的 Web 应用和文件上传场景,并且可以根据具体需求进行定制和扩展。

希望本文对你有所帮助!如果你有任何问题,请随时私信我。

相关推荐
卸任5 小时前
Vibe coding工具使用心得
前端·ai编程
brien96 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance6 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M6 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写6 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李6 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易6 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马6 小时前
前沿视界
前端
kyriewen6 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易7 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员