本项目需要涉及前端上传图片与显示图片,为此自己实践一下图片相关的东西,挺有意思所以就分享出来。
实现思路:服务端的处理方式是将前端上传的文件保存在服务端本地,然后重命名该文件名字,再将图片在服务端的路径存入表中,前端请求图片地址的时候去服务端找出文件并返回给前端显示。
在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自动生成接口文档
上一篇:待写…