egg文件上传

373 阅读1分钟

egg文件上传

  • formData表单提交的单文件通过 this.ctx.getFileStream 获取数据

前端页面

formData.append(‘myself’, 'some') 必须放到最后,否则ctx.getFileStream()对较大文件取流完成时stream.fields仍然是空的

   formData.append('myself', 'some')  // 附加字段名
   formData.append('file', file)  // 文件

egg

  1. 安装依赖 stream-wormhole

    await-stream-ready:顾名思义,能够使用await进行文件的读写操作。 stream-wormhole:在文件上传出现异常时能够把流消耗掉。

    例子中没有使用 await-stream-ready

npm i await-stream-ready -S
npm i stream-wormhole -S
  1. 引入

// const awaitWriteStream = require('await-stream-ready').write;
const sendToWormhole = require('stream-wormhole');

  1. 获取流

const stream = await ctx.getFileStream();
// stream.filename :上传的文件名称,
// stream.fields:获取附加字段 { myself: 'some' }
  1. 写入流

    // 生成文件名 这里直接用了上传文件的文件名,有需要的可以自己定义
    const target = path.join('app/public/uploads', stream.filename);
    // // 生成文件写入文件流
    const writeStream = fs.createWriteStream(target);
    try {
      await awaitWriteStream(stream.pipe(writeStream));
    } catch (err) {
      // 必须将上传的文件流消费掉,要不然浏览器响应会卡死
      await sendToWormhole(stream);
      throw err;
    }
    
    
  2. 使用例子

  async uploadPicture() {
    const { ctx } = this;
    // 获取文件对象 此对象包含所有上传携带信息
    const stream = await ctx.getFileStream();
    const userId = stream.fields.userId
    // stream.filename :文件名称,
    // stream.fields:附加字段对象
    // 结果对象
    let result = {};
    await new Promise((resolve, reject) => {
      // 保存文件,或者使用文件流做别的事情
      // ${UPLOAD_PATH}${stream.fieldname}.png 上传地址+文件名
      // stream.fieldname 对应前端:name 字段
      // stream.fields.userId 是formData附加字段属性
      const ws = fs.createWriteStream(`${UPLOAD_PATH}${userId}.${stream.mimeType === 'image/jpeg' ? 'jpg' : 'png'}`);
      stream.pipe(ws);
      ws.on('finish', () => { // 监听上传成功
        resolve();
      });
      ws.on('error', err => { // 监听上传失败
        // 必须将上传的文件流消费掉,要不然浏览器响应会卡死
        sendToWormhole(stream);
        reject(err);
      });
    }).then(() => {
      result = { data: { url: `${BASE_URL}${userId}.jpeg`} ,status: 200, massage: '上传成功' };
    }).catch(err => {
      result = { status: 204, massage: err };
    });

    ctx.body = result;
  }
js流操作例子
const fs = require("fs");

// 创建一个可读流
let readerStream = fs.createReadStream('input.txt');

// 创建一个可写流
let writerStream = fs.createWriteStream('output.txt');

// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);

console.log("程序执行完毕");