【路由中间件】文件上传
-
安装
npm i -S @koa/multer multer- 最新版本 3.0.0
-
作用
- 只会处理
multipart/form-data类型的图片/文件上传请求- 所以要在form表单上面
- 整体加
enctype="multipart/form-data" - input标签
type赋值成filename赋值成后面的avatar
<form action="/api_v1/upload_single_file" method="POST" enctype="multipart/form-data"> <input type="hidden" name="_csrf" value="<%= csrf %>" /> <input type="file" name="avatar"/> <button type="submit">upload</button> </form>- 这里如果全局开启了csrf,就算value有值,也会被无效打回,不知道为什么...所以最好不要全局开启csrf
- 如果非要全局开启csrf,就要自己加到action中
action="/api_v1/upload_single_file?_csrf=<%=csrfToken%>"
- 整体加
- 所以要在form表单上面
- 只会处理
-
在特定需要的路由中添加
-
在router前面整体引入并配置(即用即设置,不同路由可以不同配置)
import multer from "@koa/multer"; let storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, 'public/uploads/') }, filename: (req, file, cb) => { let fileFormat = (file.originalname).split("."); cb(null,Date.now() + "." + fileFormat[fileFormat.length - 1]); } }) const upload = multer({storage: storage});- 这里
storage定义了 本地磁盘存储- 需要新建文件存储路径
mkdir -p public/uploads
- 需要新建文件存储路径
storage可以是 S3存储,见下面- 重新定义了
filename,使用了13位时间戳
- 这里
-
对于 单文件 上传
router.post('/upload_single_file', upload.single('avatar'), (ctx) => { console.log(ctx.file); console.log(ctx.request.body); ctx.body = 'done'; })- 这里
ctx.file等价于ctx.request.file - 可以进一步获取文件信息,存到数据库中
ctx.file.originalname //源文件名 ctx.file.filename //文件的新名字 ctx.file.path //文件所在的完整路径 ctx.file.size //文件大小(字节) ctx.file.mimetype //文件类型
- 这里
-
对于 多文件(avatar和boop) 上传
router.post('/upload_multiple_file', upload.fields([{ name: 'avatar', maxCount: 1 },{ name: 'boop', maxCount: 2 }]), (ctx) => { console.log(ctx.request.file); console.log(ctx.file); console.log(ctx.request.body); ctx.body = 'done'; })
-
-
可配置
storage为S3存储let storage = multerS3({ s3: s3, bucket: options.Bucket, contentType: multerS3.AUTO_CONTENT_TYPE, acl: options.ACL, key: (req, file, cb) => { var fileNameFormatted = file.originalname.replace(/\s+/g, '-').toLowerCase(); cb(null, req.user.userUuid + '/' + uploadDate + '/' + fileNameFormatted); } }) -
与storage同级,可以设置
fileFilter,限制可上传文件的类型let fileFilter = (req, file, cb) => { if(!file.originalname.match(/\.(jpg|jpeg|png|gif|csv|xls|xlsb|xlsm|xlsx)$/)){ return cb('One of your selected files is not supported', false); } cb(null, true); }