nodejs multer实现文件上传功能全解(form上传、fetch请求上传、多文件上传)
前言
你能够如何实现多文件的上传吗?你知道上传时Content-Type是什么格式吗?form上传和fetch链接上传有什么区别?
本文告诉你nodejs如何使用multer进行文件的上传、获取、处理,用具体的可运行的前后端代码教会你。
安装express和multer
npm i express multer -S
基础使用
前端表单
-
enctype必须指定
multipart/form-data
,因为multer只支持这种。 -
name的值“logo”对应服务器upload.single中的“logo”。
<form action="http://localhost:3000/postFile" method="post" enctype="multipart/form-data">
<input id="postFile" type="file" name="logo">
<button type="submit">上传</button>
</form>
后端服务器文件
-
dest对应上传的文件的目录地址。
-
upload.single的值“logo”对应前端name中的“logo”。
import express from 'express'
import multer from 'multer'
const app = express()
const upload = multer({ dest: 'uploads/' })
app.post('/postFile', upload.single('logo'), (req, res) => {
res.send(req.file)
})
app.listen(3000, () => {
console.log('服务器开启中')
})
启动服务。
去页面选择文件上传一张图片,上传成功。
配置上传文件名
我们发现虽然上传了,但是文件不是我们想要的样子,没有后缀,也不知道是我们上传的图片文件。
我们可以对multer进行详细的配置。
-
destination配置上传文件的位置。
-
filename配置文件名,可以利用file上传文件的内容进行配置。
import express from 'express'
import multer from 'multer'
const app = express()
// const upload = multer({ dest: 'uploads/' })
const upload = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
// fieldname是表单的name值,也就是我们设定的“logo”,
// originalname是文件上传时的名字,可以根据它获取后缀,
// encoding,mimetype 我就不详细介绍了,可以自行输出查看。
const { fieldname, originalname, encoding, mimetype } = file
const after = originalname.split('.')[1] ? '.' + originalname.split('.')[1] : '.jpg'
cb(null, fieldname + after);
}
})
})
app.post('/postFile', upload.single('logo'), (req, res) => {
res.send(req.file)
})
app.listen(3000, () => {
console.log('服务器开启中')
})
然后我们重启服务器,再上传一次图片,就有了。
使用fetch上传文件
后端问题解决了我们看看前端的问题,表单上传文件不仅拓展差,还会跳转新页面,令人头疼。
我们去掉form表单,自定义一个上传事件。
-
我的前端页面在8080端口,也做了nginx代理请求到3000端口,你们可以自行修改成自己的请求。
-
body.append('logo', file)这里的作为key的“logo”代替了原本表单中的name值“logo”的作用。
-
虽然是post请求,但是不要添加请求头'Content-Type': 'multipart/form-data',上传文件时post已经自动帮你识别了,再加就要报错了。
<body>
<input id="postFile" type="file" name="logo">
<button type="button" onclick="upload()">上传</button>
</body>
<script>
const upload = async () => {
const body = new FormData()
const file = document.getElementById('postFile').files[0]
if (file) {
body.append('logo', file)
const response = await fetch('http://localhost:3000/postFile', {
method: 'post',
body
})
const res = await response.json()
console.log(res)
} else {
alert('请选择文件!')
}
}
</script>
多文件上传
前端表单
-
input加上multiple,支持多文件。
-
因为现在是多文件了,就不直接取文件,我们先获取用id获取dom,遍历添加进body,记得“logo”要对应后台“logo”。
<body>
<input id="postFile" type="file" name="logo" multiple>
<button type="sub" onclick="upload()">上传</button>
</body>
<script>
const upload = async () => {
const body = new FormData()
const postFile = document.getElementById('postFile')
if (postFile.files[0]) {
for (const file of postFile.files) {
body.append('logo', file)
}
const response = await fetch('http://localhost:3000/postFile', {
method: 'post',
body
})
const res = await response.json()
console.log(res)
} else {
alert('请选择文件!')
}
}
</script>
后端服务器文件
-
upload.single('logo')改成upload.array('logo', 3),后面的数字是限制上传文件数。
-
命名我们就用本来的名字,好区分不同的文件。
import express from 'express'
import mysql from 'mysql'
import multer from 'multer'
const app = express()
// const upload = multer({ dest: 'uploads/' })
const upload = multer({
storage: multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
const { fieldname, originalname, encoding, mimetype } = file
// const after = originalname.split('.')[1] ? '.' + originalname.split('.')[1] : '.jpg'
cb(null, originalname);
}
})
})
app.post('/postFile', upload.array('logo', 3), (req, res) => {
res.send(req.files)
})
app.listen(3000, () => {
console.log('服务器开启中')
})
尾言
大功告成,有帮助的话不妨点个赞吧,如果有什么问题可以评论区提出,会及时更新解决。
转载自:https://juejin.cn/post/7088125018831323172