工作不是那么忙,想学一下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. 002_centos7关闭防火墙

    防火墙是比较烦人的,在自己做实验,或者实际应用中,如果配置不好的话,会出现各种匪夷所思的问题,那么如何关闭呢 在centos7里,防火墙改为了firewalld进程 首先用命令firewall-cmd ...

  2. CSS基础知识(下)

    3.层叠 稍微复杂的样式表中都可能存在两条甚至多条规则同时选择一个元素的情况.CSS通过一种叫作层叠(cascade)的机制来处理这种冲突. 层叠机制的原理是为规则赋予不同的重要程度.最重要的是作者样 ...

  3. JAVA—继承及抽象类

    继承的概念 在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法. 与css中继承父元素属性类似 继承的 ...

  4. 2020-06-25:B+树和B树有什么区别?

    福哥答案2020-06-25: B树:1.叶子节点和非叶子节点都存数据.2.数据无链指针.B+树:1.只有叶子节点存数据.2.数据有链指针.B树优势:1.靠近根节点的数据,访问速度快.B+树优势:1. ...

  5. C#LeetCode刷题之#860-柠檬水找零(Lemonade Change)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4036 访问. 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾 ...

  6. 火题小战 B. barbeque

    火题小战 B. barbeque 题目描述 \(Robbery\) 是一个大吃货(雾) 某个神奇的串由牛肉和青椒构成,于是\(Robbery\)购买了\(n\)个餐包来自己做这个串,每个餐包中有一些牛 ...

  7. Golang Gtk+3教程:GtkBuilder使用XML构建UI

    在这节我将介绍GtkBuilder,其使我们可以从一个描述界面的xml文件构建UI.而这个文件我们可以使用Glade生成,这会极大的方便我们编辑用户界面.这节我们会使用到这么一个XML文件,名字为Bu ...

  8. 炼技术(9): 简约而不简单,永不停歇的测试 -- always_run

    最强战力,永不停歇的测试:always_run 许多工程师写完程序后,都不愿意对自己的程序做仔细测试. 很多测试说会做自动化测试,可能工作好几年都没真做过多少自动化测试. 我们的解决方案是,在系统的测 ...

  9. 带你用 Python 实现自动化群控设备

    1. 前言 群控,相信大部分人都不会陌生!印象里是一台电脑控制多台设备完成一系列的操作,更多的人喜欢把它和灰产绑定在一起! 事实上,群控在自动化测试中也被广泛使用!接下来的几篇文章,我将带大家聊聊企业 ...

  10. 【Codeforces】CF Round #592 (Div. 2) - 题解

    Problem - A Tomorrow is a difficult day for Polycarp: he has to attend \(a\) lectures and \(b\) prac ...