express中实现文件上传

介绍

之所以要单独说下文件上传,是因为body-parser中间件不支持文件类型获取。我们平时都是用这个中间件去获取post数据,但是如果post过来的是一个文件,那它就不管用了。所以,我们需要新的中间件,那就是multer

multer

Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。

关于它的用法,可以参考文档:multer

注意:Multer 不会处理任何非 multipart/form-data 类型的表单数据。

什么是 multipart/form-data类型?

表单标签form上有一个enctype属性,它有三种值:

  • application/x-www-form-urlencoded:在发送前编码所有字符(默认)
  • multipart/form-data:不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
  • text/plain:空格转换为 “+” 加号,但不对特殊字符编码。

上传一个文件

现在就来实现一个文件上传。在这之前,确保你已经安装了expressmulter

app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const express = require('express')
const app = express()

//引入multer
const multer = require('multer')

//注册一个对象,dest里放的是上传的文件存储的位置,可以在当前目录下,建立一个static目录,上传的文件都放在这里
const upload = multer({dest: './static/'})

//使用中间件,没有挂载路径,应用的每个请求都会执行该中间件。any表示接受一切,具体参考文档。
app.use(upload.any())

//在req.files中获取文件数据
app.post('/',function(req, res){

console.log(req.files)

res.send('上传成功')
})


app.listen(3000)

现在准备一个表单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form action="http://localhost:3000/" method="post" enctype="multipart/form-data">
选择文件:
<input type="file" name="file1"><br>
<input type="submit" value="上传">
</form>
</body>
</html>

注意:在form里的enctype属性上必须填”multipart/form-data”。

现在执行app.js文件

1
node app.js

在浏览器打开表单html文件,并上传一个文件,我上传了一张图片,然后在命令行里可以看到打印的数据,比如我的是:

1
2
3
4
5
6
7
8
[ { fieldname: 'file1',
originalname: 'html5.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './static/',
filename: '2047b375bfaa68f984af6ac19e8df455',
path: 'static\\2047b375bfaa68f984af6ac19e8df455',
size: 9029 } ]

可以看到req.files是一个数组,因为可能不止传一个文件,每个文件的信息也很清晰就不多介绍了。

需要注意的是filename这个属性,它就是上传后的文件名,可以到static目录里去看,它就是这样一个文件名且没有后缀,我们现在打不开它的,如果加上后缀,就可以打开了。我的图片是jpg格式,我在文件名后面加上.jpg就可以正常打开了。

手动添加后缀名太麻烦了,既然用了node,那我们何不进一步处理,直接拿到有后缀名的文件呢?

优化

其实思路很简单,看打印出的文件信息,我们可以从originalname里拿到文件后缀名,又可以在path里拿到文件路径。好了,要做的无非就是拿到后缀名再重命名嘛。使用node中的pathfs模块,很容易实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const express = require('express')
const app = express()
const multer = require('multer')

//引入 path 和 fs
const path = require('path')
const fs = require('fs')

const upload = multer({dest: './static/'})

app.use(upload.any())

app.post('/',function(req, res){
console.log(req.files)

//拿到后缀名
var extname = path.extname(req.files[0].originalname);

//拼接新的文件路径,文件加上后缀名
var newPath = req.files[0].path + extname;

//重命名
fs.rename(req.files[0].path, newPath, function(err){
if(err){
res.send('上传失败')
}else{
res.send('上传成功')
}
})
})


app.listen(3000)