本文首發(fā)于 艾特網(wǎng) - 程序員導(dǎo)航站 中的博客專欄,地址:https://www.iiter.cn/blogs/37
強(qiáng)烈建議收藏或保存
說在前面
最近想著給 艾特網(wǎng) - 程序員導(dǎo)航站 后臺(tái)擴(kuò)展文件上傳的功能。因?yàn)榭紤]到七牛云對象存儲(chǔ)比較劃算,而且每個(gè)月會(huì)
免費(fèi)贈(zèng)送 10GB
的標(biāo)準(zhǔn)存儲(chǔ)空間,基本算是白嫖
。所以就打算拿七牛云來練練手。想注冊七牛云的同學(xué)可以點(diǎn)這里
安裝依賴
七牛云官網(wǎng)中有 nodejs 版本的 sdk,我們通過 npm 來安裝
npm install qiniu
再安裝如下依賴,后面會(huì)用到
npm install await-stream-ready stream-wormhole
創(chuàng)建路由
router.js 文件中創(chuàng)建上傳文件路由,映射 utils 這個(gè) controller 下面的 uploadFiles 方法,這塊可根據(jù)自己的業(yè)務(wù)需求自行調(diào)整。
router.post("/upload", controller.utils.uploadFiles);
創(chuàng)建控制器
打開 utils 文件,創(chuàng)建 uploadFiles 方法,寫入如下內(nèi)容。
async uploadFiles() {
const { ctx } = this;
const data = await ctx.service.utils.uploadFiles();
if(data){
ctx.body = data;
}else{
ctx.body = {
message:"上傳失敗"
}
}
}
創(chuàng)建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) {
//如果出現(xiàn)錯(cuò)誤,關(guān)閉管道
await sendToWormhole(stream);
return false;
}
}
}
module.exports = utilsService;
注意:
- 代碼中這一行的
Zone_z0
應(yīng)該和自己空間的存儲(chǔ)區(qū)域相對應(yīng),不然會(huì)報(bào)錯(cuò),比方說自己空間是華北區(qū)的,對應(yīng)的就是Zone_z1
config.zone = qiniu.zone.Zone_z0;
- Access Key 和 Secret Key 可以在這里查看
https://portal.qiniu.com/user/key
上傳測試
這里用的是 postman 測試
Headers
{
"Content-Type":"multipart/form-data"
}
Body選擇form-data類型
創(chuàng)建一個(gè)key為file,右下角類型選擇File
類型,然后在value
屬性中選擇一張圖片。
點(diǎn)擊藍(lán)色的Send按鈕即可上傳
至此,一個(gè)完整的 eggjs 結(jié)合七牛云對象存儲(chǔ)的文件上傳案例就完成啦。
本文參考如下文章:
egg.js 上傳文件
NodeJS + 七牛云實(shí)現(xiàn)圖片上傳