本文首發於艾特網 - 程序員導航站 中的博客專欄,地址: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;
注意:
- 代碼中這一行的Zone_z0應該和自己空間的存儲區域相對應,不然會報錯,比方說自己空間是華北區的,對應的就是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類型
創建一個key爲file,右下角類型選擇File類型,然後在value屬性中選擇一張圖片。
點擊藍色的Send按鈕即可上傳
至此,一個完整的 eggjs 結合七牛雲存儲的文件上傳就完成啦。
本文參考如下文章:
egg.js 上傳文件
NodeJS + 七牛雲實現圖片上傳