1. 需求描述
当项目需要上传图片或文件时(比如上传头像),前端将会发送Content-Type:multipart/form-data的Post请求,将本地图片或文件上传到后端,后端将会生成对应的图片路径返回,拿到这个图片路径就能在浏览器显示或者下载这张图片啦。那具体是怎么实现的呢?下面以处理图片为例。
2. 步骤
安装mutiparty
mutiparty能够帮助我们处理mutipart/form-data的请求,拿到前端传来的文件和属性。
npm install multiparty --save
引入相关包
// 处理 mutipart/form-data
const fs = require('fs');
const multiparty = require('multiparty');
const path = require('path');
// 对时间进行格式化的函数
const Date = require('./format')
在目录下准备一个文件存储的文件夹
新建一个upload文件夹,前端上传的图片资源都会放在这个目录下的img文件夹中。
处理加载图片
定义一个upload的函数,对前端传入的图片进行处理,生成相应图片路径。
const upload = (req, res) => {
let form = new multiparty.Form()
// 设置文件存储路径
form.uploadDir = path.join(__dirname, '.././upload/img')
// 解析前端传输的文件
form.parse(req, (err, fields, files) => {
if (err) {
res.send({code:500, msg: '上传失败,' + err }))
} else {
const originalFilename = files.asset[0].originalFilename
// 旧文件路径
const oldPath = files.asset[0].path
// 新文件路径:目录 + 当前时间 + 图片名
const newPath = form.uploadDir + '/' + new Date().Format('yyyy-MM-dd-hh-mm-ss') + originalFilename
// 修改存到静态资源文件夹下的图片路径,与返回用户的路径一致
fs.renameSync(oldPath, newPath)
const formUrl = new Date().Format('yyyy-MM-dd-hh-mm-ss') + originalFilename
// 此处可以根据项目需求对数据库进行一些操作...
}
res.send(({code:200, msg: '上传成功', data: {formUrl}}))
}
})
}
module.exports = upload
为什么要用新文件路径去替代旧文件路径?
我们先来console.log(files),看看里面是长什么样子的。
如图,originalFilename是上传图片的图片名,path是默认本地的图片路径,即存储到upload/img文件夹下的图片路径。如果缺失了fs.renameSync(oldPath, newPath)这一步替换步骤,将会导致用户拿到的图片路径与后台中的图片路径不一致,如下图:
前端获取的路径:
后端存储的路径:
那在浏览器搜索引擎中输入该路径,自然是找不到目标对象啦。
为什么新图片路径的组成中要加入当前时间?
当前端多次上传同一张图片时,由于图片名相同,在静态资源目录下的图片路径也相同且唯一。但项目有时需要删除其中一张图片却不想影响到其他图片,所以要对同一张图片的多次上传以时间作为区分,产生不同的图片路径。
在index.js中将设置静态资源文件
//index.js或 app.js
app.use(express.static(path.join(__dirname, './upload')))
演示效果
本地上传图片:
静态资源目录自动增加图片:
在浏览器中输入图片路径:
注意:静态资源路径中不需要输入
/upload
这样就大功告成啦,是不是很简单呢?下载文件也是同理,感兴趣的朋友可以自己试一试。