Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

【路由中间件】文件上传

  • 安装

    npm i -S @koa/multer multer
    
    • 最新版本 3.0.0
  • 作用

    • 只会处理 multipart/form-data 类型的图片/文件上传请求
      • 所以要在form表单上面
        • 整体加 enctype="multipart/form-data"
        • input标签
          • type赋值成file
          • name赋值成后面的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%>"
          
  • 在特定需要的路由中添加

    • 在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';
      })
      
  • 可配置storageS3存储

    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);
    }