本項目需要涉及前端上傳圖檔與顯示圖檔,為此自己實踐一下圖檔相關的東西,挺有意思是以就分享出來。
實作思路:服務端的處理方式是将前端上傳的檔案儲存在服務端本地,然後重命名該檔案名字,再将圖檔在服務端的路徑存入表中,前端請求圖檔位址的時候去服務端找出檔案并傳回給前端顯示。
在routes檔案夾下建立一個common.js檔案
//common.js
//導入所需子產品
const router = require('koa-router')()
const api = require('../controllers/api')
const common = require('../util/comon')
const path = require('path')
const fs = require('fs')
const formidable = require('formidable')
const MimeLookup = require('mime-lookup')
const mime = new MimeLookup(require('mime-db'))
router.prefix('/common')
上傳圖檔
//common.js
//上傳圖檔
router.post('/addUploadImg', async (ctx, next) => {
console.log(ctx.req)
let form = new formidable.IncomingForm()
form.hash = "md5"
form.multiples = false //預設隻能上傳一個檔案,更多form的配置參考node-formidable
form.maxFileSize = 2 * 1024 * 1024 //設定檔案最大不超過2M
let type = ['image/png','image/gif','image/jpg','image/jpeg','image/webp']//支援上傳的圖檔類型
function formImage() {
return new Promise((resolve, reject) => {
form.parse(ctx.req, async function (err, fields, files) {//注意:跟express有差異,這裡要傳入ctx.req
let file = files['file']
if (file) {
let flag = await common.checkFile(file.type, file.size) //校驗檔案的大小和類型
console.log('校驗通過'+flag)
if (flag) { //檔案校驗通過
const oldpath = file['_writeStream'].path //系統緩存上傳的檔案位址
const dir = path.join(__dirname, `../common/upload/img`)
const fileFormat = file.name.split('.')
file.name = `${file.hash}_${Date.now()}.${fileFormat[fileFormat.length - 1]}` //通過file.hash加時間戳生成檔案名
const newpath = `common/upload/img/${file.name}`
if (!fs.existsSync(dir)) { //先判斷檔案夾名是否存在,不存在則生成根據XXX生成對應的檔案夾
fs.mkdirSync(dir)
}
//如果是非WINDOWS系統,可以用fs.renameSync()來實作,這裡為了相容用了node的pipe來實作
let readStream = fs.createReadStream(oldpath)
let writeStream = fs.createWriteStream(newpath)
readStream.pipe(writeStream) //這裡檔案已經上傳成功
resolve(ctx.origin + "/" + newpath) //傳回完整的檔案位址
} else {
reject(null)
}
} else {
reject(null)
}
})
})
}
await formImage()
.then(res => {
ctx.body = {
code: 200,
status: 200,
data: res,
message:'上傳成功'
}
}).catch(err => {
ctx.body = {
code: 400,
status: 200,
data: {},
message:'上傳失敗'
}
}
)
})
下載下傳圖檔
//common.js
//顯示圖檔
router.get('/upload/img/:imgUrl', async (ctx, next) => {
url=ctx.url
let index = url.lastIndexOf('/')
imgUrl = url.substring(index + 1, url.length)
let filePath = path.join(__dirname, `../common/upload/img/${imgUrl}`)
file = fs.readFileSync(filePath)//讀取檔案
// console.log(await watermark.addWatermark(file, options))
let mimeType = mime.lookup(filePath) //讀取圖檔檔案類型
ctx.set('content-type', mimeType) //設定傳回類型
ctx.body = file //傳回圖檔
})
這裡下載下傳的意思是前端拿到圖檔連結,直接img src="https:/upload/img.123sdjfhg.png"的時候服務端其實是需要響應前端的這個位址請求的,上面是收到請求後去服務端擷取圖檔并讀取然後傳回檔案回給前端。假設有做token校驗是否可以請求api的話,建議将“/common/upload/”接口的路由放入白名單(免token)中去。
檔案結構
最終在項目中呈現的結構是:
至此就完成前端圖檔上傳和下載下傳的需求了,感謝觀看!
上一篇:使用swagger自動生成接口文檔
上一篇:待寫…