工作不是那么忙,想学一下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. 用var声明变量,在java中居然有这么多细节,你都了解么?

    简介 Java SE 10引入了局部变量的类型推断.早先,所有的局部变量声明都要在左侧声明明确类型. 使用类型推断,一些显式类型可以替换为具有初始化值的局部变量保留类型var,这种作为局部变量类型 的 ...

  2. 推荐:实现RTSP/RTMP/HLS/HTTP协议的轻量级流媒体框架,支持大并发连接请求

    推荐一个比较好用的流媒体服务开源代码: ZLMediaKit: 实现RTSP/RTMP/HLS/HTTP协议的轻量级流媒体框架,支持大并发连接请求 https://gitee.com/xiahcu/Z ...

  3. OpenCV计算机视觉编程攻略(第三版)源码

    去年买了这本OpenCV的书,感觉还不错,但是书上没有给出下载源码的地方,在网上找了下,还好找到了,现在分享给大家: 链接: https://pan.baidu.com/s/1IqAay1IZ8g-h ...

  4. PXE安装与配置

    PXE 安装与配置 实验环境 VMware Fusion 虚拟机 node1有两块网卡, ens33(172.100.16.10)-->bridge, ens37-->vmnet4(192 ...

  5. 怎么在微信公众号上传PPT?

    我们都知道创建一个微信公众号,在公众号中发布一些文章是非常简单的,但公众号添加附件下载的功能却被限制,如今可以使用小程序“微附件”进行在公众号中添加附件. 以下是公众号添加附件使用“微附件”小程序的教 ...

  6. HttpClient 模拟用户操作

    首先模拟用户登录: /** * 模拟用户登录 * */ private void login() throws HttpException, IOException { PostMethod logi ...

  7. C#LeetCode刷题之#581-最短无序连续子数组( Shortest Unsorted Continuous Subarray)

    问题 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. 输入: [2, 6, 4, 8, 10, ...

  8. 微信支付.NET SDK 中的BUG(存疑)

    BUG出现在类文件WxPayData.cs中的FromXml(string xml)方法 /** * @将xml转为WxPayData对象并返回对象内部的数据 * @param string 待转换的 ...

  9. ubuntu18.04配置与美化

    一:初步系统配置 1 不可或缺的更新 如果在上一步中勾选了安装 Ubuntu 时下载更新,那么大部分的系统更新已经下载完毕. 不过为了确保,先移步到 设置→详细信息 ,点击右下角的 检查更新 ,如果存 ...

  10. Mybatis 循环删除/插入

    <foreach collection="array" open="(" separator="," close=")&qu ...