工作不是那么忙,想学一下Express+multer弄一个最简单的文件上传,然后开始npm install,然后开始对着multer官方文档一顿操作。

前台页面最简单的:

<!DOCTYPE html>
<html> <head>
<style>
</style>
</head> <body>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="text" name="username" />
<input type="file" name="avatar" />
<input type="submit" value="提交">
</form>
</body> </html>

  后台服务启用static静态文件中间件,直接访问,然后提交到/upload,后台代码如下:

const express = require('express')
const multer = require('multer')
const uuid = require('uuid/v4')
const path = require('path')
const port = 3000
const app = express()
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '../src/uploads'))
},
filename: function (req, file, cb) {
console.log(file)
let extName = path.extname(file.originalname)
cb(null, uuid() + extName)
}
})
var upload = multer({
storage: storage
})
app.use(express.static('../src/test'))
app.use('/upload', upload.single('avatar'), (req, res) => {
// 处理上传之后的逻辑
})
app.listen(port, () => {
console.log('server is listening at ' + port)
})

就这么简单,它就好像自动就给传上去了,但是不足的地方也是存在的,比如默认配置下:它不给带文件默认的扩展名,什么类型的也都接收,然后也不限制大小。

第一、首先说一下配置路径和怎么给上传之后的文件带上默认扩展名。

upload = multer({}),multer初始化的时候,如果文件路径dest不指定,那么官方文档说文件路径默认就是系统默认当前路径做为文件存储的临时路径,但是我尝试之后,发现没有报错,但是文件给上传到哪里去了,也不知道。满脸黑线!!!

然后按照官方文档,配置一下路径吧,可以直接multer({dest:'路径'}),也可以这样:

var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '../src/uploads'))
},
filename: function (req, file, cb) {
console.log(file)
let extName = path.extname(file.originalname)
cb(null, uuid() + extName)
}
})
var upload = multer({
storage: storage
})

  destination回调函数指定文件上传路径,也可以根据file的不同类型,区分不同的路径,这逻辑都取决于你自己。filename也是回调函数,上传文件怎么命名也都取决于你,它默认上传后不给带原文件扩展名,所以这部分就需要你自己给处理一下了,我这边就先拿到文件原有的扩展名,然后给上传之后的文件加上。

第二、使用fileFilter来过滤允许上传的文件类型。

multer({})配置项中除了storage之外还给出了fileFIlter属性,用来过滤允许上传的文件,它也是一个函数,根据不同的文件后缀名来选择是否允许通过。

var upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
let extName = path.extname(file.originalname)
if (extName.includes('.png')) {
cb(null, true)
} else {
// req.fileCheckError = {}
// req.fileCheckError['fileFilter'] = '只能上传png格式的文件'
cb(null, false)
}
}
})

  通过cb(null,true),第二个参数是true和false来确定是否允许通过,然后官方文档,还说第一个参数可以指定new Error来抛出一个错误,但是抛出错误之后,恐怕就需要另外写express的错误事件处理了,否则后台报错,前台是看不到东西的。官方又说话了,说multer自己不处理错误,它把错误委托给express处理了,然后用法就要变一变了,应该这样:

app.use('/upload', upload.single('avatar'), (req, res) => {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
console.log(err, 'multer error') //处理multer自身的错误
res.send(err)
} else if (err) {
console.log('normal error', err) // 处理委托给express和上传时express自身的错误
res.send(err.Error)
} else if (Object.keys(req.fileCheckError || {}).length > 0) {
console.log('req.fileCheckError', req.fileCheckError)
res.send(JSON.stringify(req.fileCheckError))
} else {
console.log('req', req.file)
let resContent = {}
resContent['username'] = req.body.username
resContent['filename'] = req.file.filename
res.send(resContent)
}
})
})

  这样写原以为cb(new Error("错误信息"),false)的错误信息会交给multer的错误处理呢,谁知道人家给委托给express的错误处理了,即便是这样,它给的是一个错误,直接扔给前端,我想要的是一个友好的提示信息,而不是扔出一大坨错误信息,那就没有办法了吗?

这个时候,有高手给出招了,说你既然中间件可以对req进行操作,为什么不对req中增加一个属性呢?一句点醒梦中人,然后fileFilter中就给req加了fileCheckError,然后再express的错误处理的时候判断一下,如果有,就友好的交给前端。

三、限制大小。

multer({limits:{}}),options里面有一个limits配置项,它同样是一个对象里面有一堆配置的东西:

fieldNameSize Max field name size 100 bytes
fieldSize Max field value size 1MB
fields Max number of non-file fields Infinity
fileSize For multipart forms, the max file size (in bytes) Infinity
files For multipart forms, the max number of file fields Infinity
parts For multipart forms, the max number of parts (fields + files) Infinity
headerPairs For multipart forms, the max number of header key=>value pairs to parse 2000

主要用到的也就是fileSize吧,超过设置大小,multer自动抛出错误到上面的multer自身处理错误中去,然后友好的发给前端就好了。

当然,以上说的这些错误,前端就可以判断了,比如类型、大小,但是都说前端的校验容易被篡改被突破,所以后端还是要校验的,毕竟网络安全无小事,万一呢。

吐槽express 中间件multer的更多相关文章

  1. express文件上传中间件Multer详解

    express文件上传中间件Multer详解 转载自:https://www.cnblogs.com/chengdabelief/p/6580874.html   Express默认并不处理HTTP请 ...

  2. 【Nodejs】Expressのファイルアップロード(FileUpload)のMulterについて

    https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md Multer 是一个 node.js 中间件,用于处理 mult ...

  3. Node.js连接Mysql,并把连接集成进Express中间件中

    引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...

  4. 1.express中间件的简介

    express中间件的意思 1, 中间件是一个模块.在js中,模块意味着函数,所以中间件是一个函数.那么这个函数长什么样子? 这还要从中间件的功能说起,它拦截http 服务器提供的请求和响应对象,执行 ...

  5. Express中间件的原理及实现

    在Node开发中免不了要使用框架,比如express.koa.koa2拿使用的最多的express来举例子开发中肯定会用到很多类似于下面的这种代码 var express = require('exp ...

  6. vue+webpack+express中间件接口使用

    环境:vue 2.9.3; webpack 目的:接口的调用 跨域方式: 1.express中间的使用 2.nginx代理 3.谷歌浏览器跨域设置 -------------------------- ...

  7. express 中间件

    [express 中间件] 中间件(Middleware) 是一个函数,它可以访问请求对象(request object (req)), 响应对象(response object (res)), 和 ...

  8. express中间件原理 && 实现

    一.什么是express中间件? 什么是express中间件呢? 我们肯定都听说过这个词,并且,如果你用过express,那么你就一定用过express中间件,如下: var express = re ...

  9. Express中间件

    一.编写中间件 中间件函数能够访问请求对象(req),响应对象(res),应用程序的请求/响应循环中的下一个中间件函数.下一个中间件函数通常由名为next的变量来表示. 中间件函数可以执行以下任务: ...

随机推荐

  1. Pytorch_第五篇_深度学习 (DeepLearning) 基础 [1]---监督学习与无监督学习

    深度学习 (DeepLearning) 基础 [1]---监督学习与无监督学习 Introduce 学习了Pytorch基础之后,在利用Pytorch搭建各种神经网络模型解决问题之前,我们需要了解深度 ...

  2. Redis服务之Redis Cluster

    在上一篇博客中我们聊到了redis的高可用组件sentinel的相关配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13429776.html:sentin ...

  3. JavaScript npm/nrm 切换安装依赖的镜像源

    nrm: npm registry manager npm 镜像源管理工具 安装nrm npm install -g nrm 查看所有的镜像源 nrm ls # nrm ls npm -------- ...

  4. 离线人脸识别门禁考勤——Android设备端APK及源码免费下载

    适用场景:门禁场景的应用,适合安装在Android系统的门口机.闸机头.Pad等设备上. 主要功能:人员注册.人脸识别开门.考勤打卡.门禁权限管理.识别记录查询等. 预览效果: PC端 设备端1 设备 ...

  5. 图的DFS和BFS(邻接表)

    用C++实现图的DFS和BFS(邻接表) 概述   图的储存方式有邻接矩阵和邻接表储存两种.由于邻接表的实现需要用到抽象数据结构里的链表,故稍微麻烦一些.C++自带的STL可以方便的实现List,使算 ...

  6. PAT 2-13. 两个有序序列的中位数(25)

    题目链接:http://www.patest.cn/contests/ds/2-13 解题思路及代码如下: /* 解题思路: 分别求出序列A 和B 的中位数,设为a 和b,求序列A 和B 的中位数过程 ...

  7. 海豚星空扫码投屏 Android 接收端 SDK 集成 六步骤

    一 跟目录的build.gradle添加私有mevan仓库 maven {url 'http://nexus.dolphinstar.cn/repo/openmavenx'} 二 app/build. ...

  8. Mybatis_day2

    二 mybatis配置详解 MyBatis最关键的组成部分是SqlSessionFactory,我们可以从中获取SqlSession, 并执行映射的SQL语句.SqlSessionFactory对象可 ...

  9. cenos 7 mysql

    CentOS 7的yum源中貌似没有正常安装mysql时的mysql-sever文件,需要去官网上下载 # wget http://dev.mysql.com/get/mysql-community- ...

  10. parallel stream-不能随便使用

    前言 java8除了新增stream,还提供了parallel stream-多线程版的stream,parallel stream的优势是:充分利用多线程,提高程序运行效率,但是正确的使用并不简单, ...