Node.js接收图片并上传至七牛云OSS
在使用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,这是在上传时添加额外参数(详情见官方文档、官方Demo、Demo文件夹),个人认为就metadata还有点用处,可以在查询图片时在header获取上传时保存的数据,当然如果你不确定你的网站会长期使用七牛云OSS不推荐设置metadata而是使用EXIF进行图片信息的保存,例如:上传者,上传时间等数据。
当然了因为七牛云的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 => { ... });
上传成功后可以获取到一个对象