本文首发于艾特网 - 程序员导航站 中的博客专栏。
地址:https://www.iiter.cn/blogs/37 建议收藏或保存

说在前面

最近想着给 艾特网 - 程序员导航站 后台扩展文件上传的功能。因为考虑到七牛云对象存储比较划算,而且每个月会免费赠送 10GB的标准存储空间,基本算是白嫖。所以就打算拿七牛云来练练手。想注册七牛云的同学可以点这里

安装依赖

七牛云官网中有 nodejs 版本的 sdk,我们通过 npm 来安装

npm install qiniu

再安装如下依赖,后面会用到

npm install await-stream-ready stream-wormhole

创建路由

router.js 文件中创建上传文件路由,映射 utils 这个 controller 下面的 uploadFiles 方法,这块可根据自己的业务需求自行调整。

router.post("/upload", controller.utils.uploadFiles);

创建控制器

打开 utils 文件,创建 uploadFiles 方法,写入如下内容。

async uploadFiles() {
    const { ctx } = this;
    const data = await ctx.service.utils.uploadFiles();
    if(data){
      ctx.body = data;
    }else{
      ctx.body = {
        message:"上传失败"
      }
    }
  }

创建service

在 service 中 utils.js 文件里完成上传逻辑

const Service = require("egg").Service;
const fs = require("fs");
const path = require("path");
const qiniu = require("qiniu");
const awaitWriteStream = require("await-stream-ready").write;
const sendToWormhole = require("stream-wormhole");
const md5 = require("md5");
const bucket = ""; //要上传的空间名
const imageUrl = ""; // 空间绑定的域名
const accessKey = ""; //Access Key
const secretKey = ""; //Secret Key
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
const options = {
  scope: bucket
};
const putPolicy = new qiniu.rs.PutPolicy(options);
const uploadToken = putPolicy.uploadToken(mac);
let config = new qiniu.conf.Config();
config.zone = qiniu.zone.Zone_z0;
class utilsService extends Service {
  async uploadFiles() {
    const { ctx } = this;
    const stream = await ctx.getFileStream();
    const filename =
      md5(stream.filename) + path.extname(stream.filename).toLocaleLowerCase();
    const localFilePath = path.join(__dirname, "../public/uploads", filename);
    const writeStream = fs.createWriteStream(localFilePath);
    try {
      await awaitWriteStream(stream.pipe(writeStream));
      const formUploader = new qiniu.form_up.FormUploader(config);
      const putExtra = new qiniu.form_up.PutExtra();
      const imgSrc = await new Promise((resolve, reject) => {
        formUploader.putFile(
          uploadToken,
          filename,
          localFilePath,
          putExtra,
          (respErr, respBody, respInfo) => {
            if (respErr) {
              reject("");
            }
            if (respInfo.statusCode == 200) {
              resolve(imageUrl + respBody.key);
            } else {
              reject("");
            }
            // 上传之后删除本地文件
            fs.unlinkSync(localFilePath);
          }
        );
      });
      if (imgSrc !== "") {
        return {
          url: imgSrc
        };
      } else {
        return false;
      }
    } catch (err) {
      //如果出现错误,关闭管道
      await sendToWormhole(stream);
      return false;
    }
  }
}
module.exports = utilsService;

注意:

  1. 代码中这一行的Zone_z0应该和自己空间的存储区域相对应,不然会报错,比方说自己空间是华北区的,对应的就是Zone_z1
config.zone = qiniu.zone.Zone_z0;

  1. Access Key 和 Secret Key 可以在这里查看
    https://portal.qiniu.com/user/key

上传测试

这里用的是 postman 测试
Headers

{
  "Content-Type":"multipart/form-data"
}

Body选择form-data类型
创建一个key为file,右下角类型选择File类型,然后在value属性中选择一张图片。

点击蓝色的Send按钮即可上传

至此,一个完整的 eggjs 结合七牛云存储的文件上传就完成啦。

本文参考如下文章:
egg.js 上传文件
NodeJS + 七牛云实现图片上传


Peanut
6 声望4 粉丝

艾特网 - 程序员导航站