工作不是那么忙,想学一下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. ubuntu apt-get 安装找不到包问题

    1.首先 sudo gedit /etc/apt/sources.list  删除全部换成国内源 (推荐163) 2.考虑 ubuntu apt-get update失败 1.出现错误:E:Could ...

  2. python3.5 continue和break 项目:买房分期付款(2)

    #案例:买房分期付款24万(10年期限) i=1#定义年份sum1=0while i<=10: print("第",i,"年到了......") if i ...

  3. 大型企业都在用的Python反爬虫手段,破了它!

    SVG 映射反爬虫 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人 ...

  4. Spring IOC 启动过程

    1. 引言 本篇博文主要介绍 IOC 容器的启动过程,启动过程分为两个步骤,第一个阶段是容器的启动阶段,第二个阶段是 Bean 实例化阶段,这两个阶段各自需要执行的步骤如下图,接下来会一一介绍. 需要 ...

  5. guice的能力简述

    guice这个google出的bean容器框架,ES有用到他. 能干什么 是一个bean容器 能AOP 能力细分与使用方式 以module创建injector.可以看成是一个容器.Module需要自定 ...

  6. pycharm激活,此方法为永久激活。

    1.下载JetbrainsCrack-3.1-release-enc.jar文件 链接: https://pan.baidu.com/s/1eN4paXtLVLeUN1nLP335rA 提取码: yg ...

  7. Python实现电脑控制,这个库让你可以控制和监控输入设备

    前言 这个库让你可以控制和监控输入设备.对于每一种输入设备,它包含一个子包来控制和监控该种输入设备:pynput.mouse:包含控制和监控鼠标或者触摸板的类.pynput.keyboard:包含控制 ...

  8. mysql 1215错误 外键建立失败

    在Mysql中创建数据表时,经常会遇到问题而失败,其中建立外键有很多细节需要我们去留意,主要有以下几种常见原因. 1.  两个字段的类型或者大小不严格匹配.例如,如果一个是int(10),那么外键也必 ...

  9. Mybatis入门(二)------增删改查

    Mybatis增删改查基本操作 一.XML实现方式 1.mapper.xml的配置 <?xml version="1.0" encoding="UTF-8" ...

  10. Docker-Docker与IPV6

    公司计划在2020年前完成IPV6化改造,于是我先行查阅了一些资料了解Docker进行IPv6化的可能性. 预计明年正式开始测试. 方法一.使容器中的服务支持IPv6地址 不为容器中的服务特别分配IP ...