Koa2 从入门到精通(三)
koa2-cors 解决跨域问题
- 参考文档
- 安装
npm install koa2-cors -S - 使用
var Koa = require('koa');
var cors = require('koa2-cors');
var app = new Koa();
app.use(cors({
origin: function(ctx) {
if (ctx.url === '/test') {
return false;
}
return '*';
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}));
@koa-multer处理图片上传
此处对于图片文件的处理并没有进行完全封装,可根据你的实际需求或情况自行封装,此处详细讲解,单图片上传和多图片上传
-
安装
npm install @koa/multer multer -S -
单文件上传使用single方法,多文件上传使用array或者fields
-
在utils文件夹中定义图片上传的操作,为工具类文件, 此处未封装成函数,如果有需要自行根据个人需求进行封装,utils/imageUpload.js
需要注意的是存储引擎设置的,文件路径必须得存在,不然会报错,此处我新建了public/images文件夹用来存放图片
// utils/imageUpload.js
const multer = require('@koa/multer')
const path = require('path')
// 设置磁盘存储引擎,设置上传文件存放路径、及文件命名,其中images文件夹必须存在,否则会报错
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/images')
},
filename: function (req, file, cb) {
let ran = Math.floor(Math.random()*10000) // 此处随机生成一万以内的整数,来尽量避免重复
let ext = file.originalname.split('.')[1]
let fileName = `${Date.now()}${ran}.${ext}`
cb(null, fileName)
}
})
// 文件上传限制,文件数量,文件大小等限制
const limits = {
// fileSize: 250 * 1024, // 文件大小 单位: b ,上面还有kb,mb,所以1024相当于1024b == 1.024kb
// files: 1 // 文件最大数量
}
// 文件类型过滤
function checkFileType(file, cb) {
// 允许的扩展名格式
const filetypes = /jpeg|jpg|png|gif/
const extname = filetypes.test(path.extname(file.originalname).toLowerCase())
const mimetype = filetypes.test(file.mimetype)
if (mimetype && extname) {
return cb(null, true)
} else {
// 上传文件的格式错误
cb({
message: 'file type error'
})
}
}
// 加载配置,当类型检查和大小限制等一系列的限制回调被执行,会被app.on('error')捕获到
const upload = multer({
storage,
fileFilter: function(req, file, cb) {
checkFileType(file, cb)
},
limits
})
module.exports = upload
单图片文件上传
- 在路由中定义 upload.js 文件,用于处理上传api,并在app.js中使用该路由
const users = require('./routes/users')
const uploads = require('./routes/upload')
app.use(users.routes(), users.allowedMethods())
app.use(uploads.routes(), uploads.allowedMethods())
const router = require('koa-router')()
const upload = require('./../utils/imageUpload')
const { SuccessModel, ErrorModel} = require('./../model/resModel')
router.prefix('/upload')
router.post('/image/single', async function (ctx, next) {
let err = await upload.single('file')(ctx, next)
.then(res=>res).catch(err=>err)
// 错误捕获
if (err) {
ctx.body = new ErrorModel(err.message)
} else {
if (ctx.file == undefined) {
ctx.body = new ErrorModel('不能上传空')
} else {
ctx.body = new SuccessModel('success')
}
}
})
module.exports = router
- 前端使用情况
传递的文件必须为表单数据 multipart/form-data
const formData = new FormData(); formData.append('file', file)
多图片文件上传
- 使用upload.array()
const router = require('koa-router')()
const upload = require('./../utils/imageUpload')
const { SuccessModel, ErrorModel} = require('./../model/resModel')
router.prefix('/upload')
router.post('/image/single', async function (ctx, next) {
let err = await upload.single('file')(ctx, next)
.then(res=>res).catch(err=>err)
// 错误捕获
if (err) {
ctx.body = new ErrorModel(err.message)
} else {
if (ctx.file == undefined) {
ctx.body = new ErrorModel('不能上传空')
} else {
ctx.body = new SuccessModel('success')
}
}
})
router.post('/image/multer', async (ctx, next) => {
// upload.array(name, maxCount) name表示上传时字段名称,maxCount表示最大数量
let err = await upload.array('file', 6)(ctx, next)
.then(res=>res).catch(err=>err)
// 错误捕获
if (err) {
ctx.body = new ErrorModel(err.message)
} else {
if (ctx.files.length) {
ctx.body = new SuccessModel('success')
} else {
ctx.body = new ErrorModel('不能上传空')
}
}
})
module.exports = router
- 前端使用情况
<template>
<div>
<input type="file" @change="change" ref="val" multiple>
</div>
</template>
<script>
export default {
name: 'Test',
methods: {
change() {
var formData = new FormData()
var len = this.$refs.val.files.length;
for (var i = 0; i < len; i++) {
formData.append('file', this.$refs.val.files[i])
}
this.$axios.post('http://localhost:3000/upload/image/multer', formData).then(res => {
console.log(res)
})
}
}
}
</script>
<style scoped>
</style>
- 选择的多个文件中,存在其他非图片格式的文件
- 都选择图片格式的图片,且数量没有超过限制
- 都选择图片格式,但数量超过了设置的6张的限制
多张图片上传二
- 相当于upload.array()的升级版,可以传递多个字段
const router = require('koa-router')()
const upload = require('./../utils/imageUpload')
const { SuccessModel, ErrorModel} = require('./../model/resModel')
router.prefix('/upload')
router.post('/image/single', async function (ctx, next) {
let err = await upload.single('file')(ctx, next)
.then(res=>res).catch(err=>err)
// 错误捕获
if (err) {
ctx.body = new ErrorModel(err.message)
} else {
ctx.body = new SuccessModel('success')
}
})
router.post('/image/multer', async (ctx, next) => {
// upload.array(name, maxCount) name表示上传时字段名称,maxCount表示最大数量
let err = await upload.array('file', 6)(ctx, next)
.then(res=>res).catch(err=>err)
// 错误捕获
if (err) {
ctx.body = new ErrorModel(err.message)
} else {
ctx.body = new SuccessModel('success')
}
})
router.post('/image/multer-fields', async (ctx, next) => {
// upload.fields([{name: '', maxCount: number}])
let err = await upload.fields([{
name: 'file1',
maxCount: 1,
}, {
name: 'file2',
maxCount: 2
}
])(ctx, next)
.then(res=>res).catch(err=>err)
// 错误捕获
if (err) {
ctx.body = new ErrorModel(err.message)
} else {
// ctx.files是一个对象里面包含了 {file1:[], file2: []}
console.log(ctx.files)
ctx.body = new SuccessModel('success')
}
})
module.exports = router
- 前端使用情况,此处就不进行测试了,字段可传可不传
上传进度条
- 参考博客
- 参考博客包含多种网络请求的介绍 XMLHttpRequest、jQuery.ajax、axios
- 对于上传进度无需后端做过多操作,只需要有上传文件的接口就行了,对于上传进度由前端进行监听
- 使用,此处上传图片文件比较小,上传速度有点快看不出效果,我手动吧网络调慢了
<template>
<div>
<input type="file" ref="val" multiple>
<div>
<progress id="progress" :value="progress" max="100"></progress>
<span>{{progress}}%</span>
</div>
<button @click="upload">上传</button>
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
progress: 0
}
},
methods: {
upload() {
let config = {
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: e => {
const { loaded, total } = e
if (e.lengthComputable) {
let progress = loaded / total * 100
// 向下取整,去掉小数
progress = Math.floor(progress)
console.log(progress)
this.progress = progress
}
}
}
var formData = new FormData()
formData.append('file', this.$refs.val.files[0])
console.log(formData.get('file'))
this.$axios.post('http://localhost:3000/upload/image/single', formData, config).then(res => {
console.log(res)
})
}
}
}
</script>
<style scoped>
</style>