vue实现文件上传与下载
一、文件上传(多个文件上传)
1、文件上传弹窗代码:
<!--================================上传文件弹窗=========================--> <el-dialog :title="addFileTitleName" :visible.sync="dialogAddFile" width="500px" style="padding:0;" @close="resetAddFile" > <el-input v-model="addFileName" autocomplete="off" size="small" style="width: 300px; display: none;" ></el-input> <div class="add-file-right" > <input type="file" ref="clearFile" @change="getFile($event)" multiple="multiplt" class="add-file-right-input" style="margin-left:70px;" accept=".docx,.doc,.xls,.xlsx,.ppt,.pptx,.pdf,.txt"> <div style="margin-top: 20px;"> <span class="add-file-right-more">支持扩展名:.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,txt </span> </div> </div> <div class="add-file-list"> <ul> <li v-for="(item, index) in addArr" :key="index"><a >{{item.name}}</a></li> </ul> </div> <div slot="footer" class="dialog-footer"> <el-button type="primary" @click="submitAddFile" size="small">开始上传</el-button> <el-button @click="resetAddFile" size="small">全部删除</el-button> </div> </el-dialog>
2、文件上传对话框里面对应的参数和上传方法,js代码:
//============上传文件参数初始化========================================== dialogAddFile: false,//上传文件弹窗 addFileTitleName: "上传文件窗口", addFileName: "", addArr: [],
三个js方法:
//==================上传文件操作函数=============================================
getFile(event){ //获取上传文件方法
var file = event.target.files;
for(var i = 0;i<file.length;i++){
// 上传类型判断
var imgName = file[i].name;
var idx = imgName.lastIndexOf(".");
if (idx != -1){
var ext = imgName.substr(idx+1).toUpperCase();
ext = ext.toLowerCase( );
//pdg,doc,docx.xls,.xlsx,.ppt,pptx,
if (ext!='pdf' && ext!='doc' && ext!='docx' && ext!='xls' && ext!='xlsx' && ext!='ppt' && ext!='pptx' && ext!='txt'){
}else{
this.addArr.push(file[i]);
}
}else{
}
}
},
submitAddFile(){ //===========提交上传文件到后台保存方法
if(0 == this.addArr.length){
this.$message({
type: 'info',
message: '请选择要上传的文件'
});
return;
}
var formData = new FormData();
for(var i=0;i<this.addArr.length;i++){
formData.append('files',this.addArr[i]);
}
let config = {
headers: { "Content-Type": "multipart/form-data" }
};
console.log(formData);
//接口请求使用的是自己封装了一下的axios
this.$http.post('/xxxx/uploadMyFile', formData, config).then(res => {
console.log(res);
this.$message({
message: '操作成功',
type: 'success'
});
}).catch((error) => {
alert("操作失败,出现错误:" + error)
});
},
//清除上传的文件方法
resetAddFile(){
this.addFileName = "";
this.addArr =[];
},
3、java后端接口代码:
/** * (上传文件) * @param file * @return */ @RequestMapping( value = "/uploadMyFile", method = RequestMethod.POST) @ResponseBody public ResultBase<String> uploadMyFile(@RequestParam(value = "files" , required = true) MultipartFile[] files){ log.info("uploadImg方法上传图片开始"); ResultBase<String> rb = new ResultBase<String>(); try { log.info("调试打印:" + files.clone()); rb.setCode(0); } catch (Exception e) { rb.setCode(1); log.error("uploadMyFile方法操作异常:" + e); } return rb; }
=============亲测无误,前端效果图==========================
二、文件下载====================================================================================================
重点记下:
cao,cao,cao,使用axios请求有个巨坑,在百度了很多次后发现axios不管用get还是用post请求,后端代码控制浏览器弹出下载是无效的,导致要在请求返回结果的数据流里用js转成Blob对象,再用js调起浏览器的下载弹窗,代码示例如下:
【文件下载虽然实现了,巨坑就来了,用这块代码下载的文件内容中文的全是乱码,不管在java代码怎么设置repsonse的编码格式,没 一 点 卵 用】
this.$http.get('/xxxx/downMyFile').then(res => { console.log("下载文件返回res"); console.log(res); if(!res.data){ this.$message.error("下载内容为空"); return; } let url = window.URL.createObjectURL(new Blob([res.data], {type: 'application/octet-stream'})); let link = document.createElement('a'); link.style.display = 'none'; link.href = url; // const fileName = res.headers["content-disposition"].split(";")[1].split("=")[1];//文件名称 const fileName = obj.file_name;//文件名称 link.setAttribute('download', fileName); document.body.appendChild(link); link.click(); window.URL.revokeObjectURL(url);//释放url对象所占资源 document.body.removeChild(link);//用完删除 this.$message({ message: '操作成功', type: 'success' }); }).catch((error) => { alert("操作失败,出现错误:" + error) });
最后怎么解决的呢,不用axios的请求,直接用window.location.href打开后端下载接口地址,完美解决:
var objParam = "?url=" + row.url + "&file_name="+row.file_name; //地址后面带的参数,根据自己业务来 window.location.href = 'xxx/xxxx/downloadMyFile'+objParam;
后面java代码:
@ApiOperation("") @RequestMapping(value = "/downloadMyFile", method = RequestMethod.GET) public void downloadMyFile(HttpServletRequest request, HttpServletResponse response) { log.info("downloadMyFile方法"); try { String url = request.getParameter("url"); String file_name = request.getParameter("file_name"); ServletOutputStream os = null; // File file = new File("D:\\testSaveFile\\8ef7672a14ea4362b6bd48a1743b01c0测试上传文件.docx"); File file = new File(savefilepath+url); //savefilepath:为写死文件所在地址:D:\\testSaveFile\\ // String filename = file.getName(); FileInputStream fileInputStream = new FileInputStream(file); InputStream fis = new BufferedInputStream(fileInputStream); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); // 清空response response.reset(); // 设置response的Header response.setContentType("text/html;charset=utf-8"); //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存 //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3" // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称 // filename=filenameEncoding(filename,request); response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file_name, "UTF-8")); // 告知浏览器文件的大小 response.addHeader("Content-Length", "" + file.length()); OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); response.setContentType("application/octet-stream"); outputStream.write(buffer); outputStream.flush(); outputStream.close(); } catch (Exception e) { log.error("uploadMyFile方法操作异常:" + e); }
参考文章:http://blog.ncmem.com/wordpress/2023/10/26/vue%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e4%b8%8e%e4%b8%8b%e8%bd%bd/
欢迎入群一起讨论