工作不是那么忙,想学一下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. 我是键盘侠-键盘流神器Vimium

    黑客的浏览器. Vimium本着Vim的精神为导航和控制提供键盘快捷键. 注意:谷歌不允许 Vimium在 Chrome Web Store页面和 新选项卡页面上运行.所以按键无效不要惊讶 Vimiu ...

  2. RabbitMq之消息确认

    最近阅读了rabbitmq的官方文档,然后结合之前面试时被问到关于消息队列的问题来探索一下关于消息队列的消息确认机制. 其实消息确认就是消费者确认消息被消费了, 生产者确认消息已经发送到了消息队列中了 ...

  3. MySQL回顾

    一. 对数据库的操作 1. 创建一个库 create database 库名 create database 库名 character set 编码 创建带有编码的 查看编码: 2. 删除一个库 dr ...

  4. sockjs.js?9be2:1606 GET http://192.168.1.101:8080/sockjs-node/info?t=1583642185049 net::ERR_CONNECTION_TIMED_OUT错误连接方式解决方法

    在使用vue-cli脚手架创建项目的时候,在cnpm create app命令后,项目创建成功后通过npm run serve命令运行以后,控制台报错,sockjs.js?9be2:1606 GET ...

  5. 正确认识springcloud的作用。分布式从了解架构到springcloud支撑

    转载于 https://www.cnblogs.com/williamjie/p/9369681.html 基于springCloud的分布式架构体系   Spring Cloud作为一套微服务治理的 ...

  6. django python manage.py runserver 流程

    python manage.py runserver 流程分析 版本 python27 django 1.0 搭建可运行的环境 创建python27 虚拟环境 github 下载 django-1.0 ...

  7. SPP、ASPP、RFB、CBAM

    SPP:ASPP:将pooling 改为了 空洞卷积RFB:不同大小的卷积核和空洞卷积进行组合,认为大的卷积应该有更大的感受野. CBAM:空间和通道的注意力机制 SPP: Spatial Pyram ...

  8. Flink的状态编程和容错机制(四)

    一.状态编程 Flink 内置的很多算子,数据源 source,数据存储 sink 都是有状态的,流中的数据都是 buffer records,会保存一定的元素或者元数据.例如 : ProcessWi ...

  9. 【LeetCode/LintCode】 题解丨字节跳动试题:第k大的子数组

    给定一个长度为n的数组a,它有n(n+1)/2​​个子数组.请计算这些子数组的和,然后按照升序排列,并返回排序后第k个数. 1≤n≤10​^5 1≤a​i≤10^​9 1≤k≤​n(n+1)/2 在线 ...

  10. C++中简单程序出现Segmentation fault (core dumped)段错误

    段错误就是指访问的内存超出了系统所给这个程序的内存空间.一般是随意使用野指针或者数组.数组越界. ------两种简单解决方法:1.利用GDB调试,定位出错位置.(具体可查找博客详细学习)2.在可能出 ...