前言: 我今天在实现一个文件的上传下载的功能,遇到了一些坑,现在都已经解决了,所以来记录一下。
上传的坑:
我用的是elementUI的组件库里面自带上传。
我们先来看一下这个组件的基本用法
<el-upload
class="upload-demo"
drag
action="/upload"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
上面是官方的一个例子,注意一下这个action,一般看到这里,就以为是请求接口
然后这是我的上传接口
app.post('/upload',async (req,res)=>{
const files = req.files
if(files.length === 0){
res.json({
code:201,
msg:'上传文件为空',
data: null
})
}else{
for (const item of files) {
fs.renameSync('./files/' + item.filename, './files/' + item.originalname); //这里修改文件名。
}
res.json({
code:200,
msg:'上传文件成功',
})
}
})
看起来好像都没问题,可是这两者就是连接不起来,接口那边也没有反应,所以我检查了好几遍,但是发现实在没问题啊。
后面我用postman测试了一下接口,发现其实功能正常,到这里我明白了,就是前端代码的问题,因为我前端还没有写多少代码,所以我一下子就锁定到了el-upload组件上。看了一遍他的参数。
action是必传的没错呀,没问题的吧,路径也是写对了的
直到我看到了http-request
这个属性
到这里我明白了,action
这个属性可能是上传的服务器的路径,并不是请求接口
问了下度娘,发现还真的是。。。
所以我给http-request绑定了一个方法,打印了一下这个方法的参数
是一个文件对象,又查了一下百度,发现要用到FormData
对象,还要设置请求头1,所以这里我又改了一下接口
function fileUpload (fileobj) {
let param = new FormData()
// 上传文件对象 名称file与后台控制器参数要一致
param.append('file', fileobj.file)
return axios({
method: 'post',
// 上传地址
url: 'http://localhost:8080/upload',
// 定义上传头
headers: {'Content-Type': 'multipart/form-data'},
data: param
})
}
到这里就能够正常地进行文件上传啦!!!!
**文件下载:**文件下载也是坑了我一会,首先我想到的是使用fs模块自带的读取文件流返回给前端再进行处理的,但是前端接收到的参数却是一个ArrayBuffer,这样好像不能处理哦。
那没办法,后面又了解到可以使用res.download来返回下载文件,但是到浏览器打开控制台一看,返回了一串乱码,如图
又查了下百度,才知道原来是 ajax 只能以字符型读取 res,并不能调用浏览器下载相关的机制。
所以只能用a标签来触发下载,同时在查阅过程中我还发现了blob对象(二进制类型的大对象)
可以将二进制的ArrayBuffer传给blob,再生成一个链接,再通过生成一个a标签来下载总体代码就是
function downloadFile (data, fileName) {
let blob = new Blob([data])
// 生成a标签
let downloadElement = document.createElement('a')
// 创建下载的链接
let href = window.URL.createObjectURL(blob)
// a的下载链接
downloadElement.href = href
// 设置下载后文件名
downloadElement.download = fileName
// 添加a标签
document.body.appendChild(downloadElement)
// 点击下载
downloadElement.click()
// 下载完成移除元素
document.body.removeChild(downloadElement)
// 释放掉blob对象
window.URL.revokeObjectURL(href)
}
这两个功能就写好了,踩坑完毕