likes
comments
collection
share

Node.js接收图片并上传至七牛云OSS

作者站长头像
站长
· 阅读数 698

在使用Node.js机型服务端开发时,我们经常使用OSS来作为图床,文章讲解了使用Koa作为HTTP框架、使用七牛云OSS存储图片、使用multer接收图片的具体操作方法。

定义路由

Koa和Express在基本使用上没啥区别,本文以Koa为例。

定义一个路由然后在index.ts中注册一下即可,非常简单。

import Router from "@koa/router";
let router = new Router();

router.post("/static/:folder", async ctx => {
  
  ctx.body = { key: "value" };
});
export default router;

配置multer

接收上传的图片我们无需保存成图片,使用Buffer保存在内存中即可,上产时直接上传Buffer。

可以设置允许接收的格式,接收个数,限制大小,以及上传时候的key

import Router from "@koa/router";
let router = new Router();
import multer from "@koa/multer";
// import sharp from "sharp";
import qiniu from "qiniu";
import { v4 } from "uuid";//将图片名修改为UUID



let upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    files: 1,//1张
    fileSize: (2 * 1024) //2MB
  },
});

router.post("/static/:folder", upload.single("image")/**上传key为image**/, async ctx => {
  let buffer = ctx.file.buffer;

  ctx.body = { key: "value" };
});
export default router;

使用组件上传时候设置一下name,如果自定义上传:FormData.append("image",file[0]),在向new FormData()中添加文件时设置image

这样使用ctx.flle可以直接拿到上传的信息,其中包裹buffer属性

上传OSS

道理同样简单,使用七牛云给的AK和SK结合上传的空间名字来算出token设置好保存文件的名字,直接上传Buffer。

import Router from "@koa/router";
let router = new Router();
import multer from "@koa/multer";
import sharp from "sharp";
import qiniu from "qiniu";
import { v4 } from "uuid";
import sync from "@/utils/useSync";
let config = new qiniu.conf.Config({
  zone: qiniu.zone.Zone_z2,
});

let upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    files: 1,
    fileSize: 1024 * 1024 * 3, //3mb
  },
});

let accessKey = process.env.QINIU_AK;
let secretKey = process.env.QINIU_SK;
let bucket = process.env.OSS_NAME;

router.post("/static/:folder", upload.single("image"), async ctx => {
  let mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
  let options = {
    scope: bucket,
  };
  let putPolicy = new qiniu.rs.PutPolicy(options);
  let uploadToken = putPolicy.uploadToken(mac);

  let buffer = ctx.file.buffer;
  let fileName = `${v4()}.webp`;

  var formUploader = new qiniu.form_up.FormUploader(config);
  var putExtra = new qiniu.form_up.PutExtra();
  await sync(resolve => {
    sharp(buffer)
      .webp({
        quality: 90,
        lossless: true,
      })
      .toBuffer()
      .then(data => {
        formUploader.put(
          uploadToken,
          fileName,
          data, //压缩后的buffer
          putExtra,
          function (respErr, respBody, respInfo) {
            if (respErr) {
              ctx.body = { success: true, message: "上传错误" };
              resolve();
              throw respErr;
            }
            if (respInfo.statusCode == 200) {
              ctx.body = {
                success: true,
                message: "上传成功",
                data: { file_name: respBody.key, file_href: `${process.env.CDN}/${respBody.key}` },
              };
            } else {
              ctx.status = respInfo.statusCode;
              ctx.body = { success: false, message: "上传错误" };
            }
            resolve();
          }
        );
      })
      .catch(err => {
        ctx.body = { success: false, message: "上传错误" };
        resolve();
      });
  });
});
export default router;

在准备上传时可以设置putExtra,这是在上传时添加额外参数(详情见官方文档官方DemoDemo文件夹),个人认为就metadata还有点用处,可以在查询图片时在header获取上传时保存的数据,当然如果你不确定你的网站会长期使用七牛云OSS不推荐设置metadata而是使用EXIF进行图片信息的保存,例如:上传者,上传时间等数据。

Node.js接收图片并上传至七牛云OSS当然了因为七牛云的OSS和CDN对图片的处理是收费的,如果想在上传前对图片进行处理开源使用Sharp插件,进行图片的格式转换,调整大小和旋转,压缩以及水印和Exit编写,这是一款非常强大的图片处理插件,在图片上传时你一定会需要压缩和格式转换的功能:

sharp(`public/image/${filename}`)
      .webp({
        quality: 80,
      })
      .toFile(`public/image/${option.dir}/${option.name || id}.webp`)
sharp('input.jpg')
  .rotate()//旋转
  .resize(200)//设置大小
  .webp({
        quality: 80,
   })//转为webp保留80%清晰度  .toBuffer()
  .then( data => { ... })//处理成功后获取buffer
  .catch( err => { ... });

上传成功后可以获取到一个对象

Node.js接收图片并上传至七牛云OSS