笔记:简单的前端大文件切片上传、上传进度(progress)逻辑

320 阅读1分钟

重点内容:

![UNVWJG_NBX)OUDSH8O3YJX.png

获取文件对象,主要取出name,size,type元素。

要将文件切成若干分,也是我们要手动拟定的。
const CHUNK_SIZE = 1024 * 1024;

主要逻辑块

const { name, type, size } = file; // 文件对象解构,取出主要内容
progress.value.max = size; //progress进度条设置最大进度(文件size总大小)
const fileName = new Date().getTime() + "_" + name; //文件名,文件名必须是唯一标识,不能重复

let uploadedSize = 0; //累加后,已上传的文件大小

// 循环,开始切割文件,如果已上传文件大小小于文件总大小,就一直循环调用上传接口
while (uploadedSize < size) {
  // 用slice方法对文件进行分段切割
  const fileChunk = file.slice(uploadedSize, uploadedSize + CHUNK_SIZE);
  
  // formData对象传递后后端接口封装,封装代码见如下
  const formData = createFormData({
    name,
    type,
    size,
    fileName,
    uploadedSize,
    fileChunk
  });

  // 调用上传接口,传递formData
  try {
    const uploadResult = await $axios.post(
      "http://localhost:8000/uploadFile",
      formData
    );
  } catch (e) {
    alert(UPLOAD_INFO["UPLOAD_FAILED"]);
    return;
  }

  // 已上传文件数量
  uploadedSize += fileChunk.size;
  // 根据已上传文件数量 设置进度条
  progressVal.value = uploadedSize;

formData封装

const createFormData = ({
  name,
  type,
  size,
  fileName,
  uploadedSize,
  fileChunk,
}) => {
  const fd = new FormData();

  fd.append("name", name);
  fd.append("type", type);
  fd.append("size", size);
  fd.append("fileName", fileName);
  fd.append("uploadedSize", uploadedSize);
  fd.append("file", fileChunk);
  return fd;
};

接下来是后端部分,后端部分用的nodeJS + Express进行简单实现

/*
    引入主要模块
    @existsSync 判断文件是否存在于目录下
    @appendFileSync 如果不存在文件,新写文件
    @writeFileSync 文件存在,继写文件
*/
const { existsSync, appendFileSync, writeFileSync } = require('fs');

// 处理前端传递过来的二进制文件模块
const uploader = require('express-fileupload');

//主要代码,上传接口
app.post('/uploadFile', (req, res) => {
    const {
        name,
        type,
        size,
        fileName,
        uploadedSize,
    } = req.body;
    
    const { file } = req.files; // 二进制文件

    if(!file){
        res.send({
            code: 1001,
            msg: 'No File Uploaded'
        });
        return;
    }

    if(!ALLOWED_TYPE[type]){
        res.send({
            code: 1002,
            msg: '文件格式不正确,请重试'
        });
        return;
    }

    const filePath = resolve(__dirname, './upload_temp/' + fileName); //存放文件目录

    if(uploadedSize != 0){
        //判断目录下是否有文件,如果没有就新写文件
        if(!existsSync(filePath)){
            //添加文件
            appendFileSync(filePath, file.data);
            res.send({
                code: 0,
                msg: 'Appended',
                data: {
                    video_url: 'http://localhost:8000/' + fileName
                }
            });
            return;
        }
    }

    // 存在已有文件,继写文件
    writeFileSync(filePath, file.data);
    res.send({
        code: 0,
        msg: 'File is Created',
        data: {
            video_url: 'http://localhost:8000/' + fileName
        }
    });
});