Egg代理文件上传

遇到这个需求时候,疯狂百度搜索浏览几篇博客之后,看到解决方案大致分为两种:

  • 代理上传流
  • 先接收文件并写入,再代理请求上传

大多数文章都介绍的是第二种先接收文件并写入,再代理请求上传,这种方式无论是Egg自带的 HttpClient,还是superagent、request(已停止更新,不推荐使用)都是支持的。第一种代理上传流(单文件),目前只发现superagent支持(其他或许支持流,但需要先接收文件并写入)。接下来介绍解决方案。

先接收文件并写入,再代理请求上传

这种有很多种,本文只举例一个

依赖安装

npm i stream-wormhole await-stream-ready md5 -S

Service

'use strict';

const Service = require('egg').Service;
const path = require('path');
const sendToWormhole = require('stream-wormhole');
const fs = require('fs');
const awaitWriteStream = require('await-stream-ready').write;
const md5 = require('md5');
class formService extends Service {
  async upload(url) {
    const { ctx, config } = this;
    const allUrl = config.api.headUrl + url;
    const stream = await ctx.getFileStream();
    // 为了不重名,一波操作猛如虎(不用文件内容计算md5,是怕文件内容过大)
    const reName = md5(ctx.get('content-length') + new Date().getTime() + stream.filename) + stream.filename;
    const target = path.join(config.baseDir, 'app/public', reName);
    const writeStream = fs.createWriteStream(target);
    let result;
    try {
      await awaitWriteStream(stream.pipe(writeStream));
      result = await ctx.curl(allUrl, {
        method: 'POST',
        dataType: 'json',
        headers: {
          token: ctx.get('token'),
        },
        // 单文件上传
        files: target,
      });
    } catch (err) {
      // 如果出现错误,关闭管道
      await sendToWormhole(stream);
      ctx.throw(500, err);
    }
    // 在上传完毕后删除文件
    fs.unlink(target, err => {
      if (!err) {
        console.log('文件已删除:', target);
      }
    });
    return result;
  }
}

module.exports = formService;

我不喜欢这种方式,因为需要写入文件,然后又删除。

代理上传流

依赖安装

npm i stream-wormhole superagent stream-to-array -S

Service

'use strict';

const Service = require('egg').Service;
const request = require('superagent');
const sendToWormhole = require('stream-wormhole');
const toArray = require('stream-to-array');
class formService extends Service {
  async upload(url) {
    const { ctx, config } = this;
    const allUrl = config.api.headUrl + url;
    const stream = await ctx.getFileStream();
    let result;
    try {
      const arrStream = await toArray(stream);
      const bufFile = Buffer.concat(arrStream);
      result = await request
        .post(allUrl)
        .attach('file', bufFile, stream.filename)
        .set('token', ctx.get('token'));
    } catch (err) {
      // 如果出现错误,关闭管道
      await sendToWormhole(stream);
      ctx.throw(500, err);
    }
    return {
      ...result,
      data: result.body,
    };
  }
}

module.exports = formService;
参考链接:

https://juejin.im/post/6844903969865777165

https://www.yuque.com/egg/nodejs/httpclient-upload

https://www.jianshu.com/p/56bfdae6f5c6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值