上传下载文件--文件流做法
1.上传文件
第一步:写上传按钮界面
<el-form :model="dataForm" :rules="rules">
<el-form-item label="文件上传:" prop="fileList">
<el-upload
class="upload-demo"
:before-remove="beforeRemove" // 删除上传成功的文件列表
multiple
:limit="1"
:on-exceed="handleExceed"
action="" // 重点 设置为空
:auto-upload="false" // 自动上传设置为false,因为要点击确认之后才去调接口
:file-list="dataForm.fileList" // 列表呈现
:on-change="handleFileChange"> // 文件有变化的时候要调用
<el-button size="small" type="primary">点击上传</el-button>
<!--<div slot="tip"class="el-upload_tip">
只能上传jpg/png文件,且不超座06kb
</div>-->
</el-upload>
</el-form-item>
</el-form>
第二步:调用on-change事件,把选择的文件赋值到本地this.dataForm.fileList
handleFileChange(file,fileList){
//console.log("file",file);
// file是指只上传一个文件的时候用,fileList是上传多个文件的时候用的参数
// 因为:before-upload="beforeAvatarUpload"限制格式的事件不能与auto-upload="false"共用,否则是不生效功能的,所以就只能提通过文件改变时去处理限制格式
const fileName = filelist[0].name;
const fileNum = fileName.lastIndexof(".");
const fileType fileName.substring(fileNum ,1);
const fileBlob fileType ="xlsx";
if (!fileBlob){
this.$message.error("文件只限上传xsxl格式的");
this.dataForm.fileList = []
}else{
this.dataForm.fileList = filelist;
}
第三步就是拿到文件的fileList之后,点击确认上传 ,用formDdata的形式给到接口做参数(完成)
//上传和api处理
async handleUploadFile(){
const file = this.dataForm.fileList[];
console.log("file",file);
const formData = new FormData();
// 后端需要的参数
formData.append("file",file.raw);
formData.append("taskName",this.dataForm.taskName);
console.log("formData",formData);
this.fileLoading = true;
const data = await uploadFile(formData);
if (data.data.success){
this.fileLoading false;
this.handclear();
this.$smessage.success('上传成功')
this.$emit("getTaskbaseinfo");
}else{
this.fileLoading = false;
}
},
1.2 另外一种的给到后端的方式则是以url的形式传递,这个时候得用到new FormData()进行数据的传递调接口
const formData = new FormData()
formData.append('file',数据)
formData.append('fileName',数据)
...
调接口例如changeUrl(formData)
然后传给后端
2.下载文件流
第一种:封装下载文件流的函数(URL为封装版本)
import request from '@/router/axios'
export async function download(url,method = 'get',query){
try{
return request({
url:url,
method:"get",
responseType:"blob",
params:query,
}).then((res)=>{
console.log(res);
console.log(res.data)
if (res.data.success ==true){
const fileName = decodeURIComponent(res.headers['content-disposition'].split('=')[1]);
(Content-Disposition,对后端给的filename进行解码)
浏览器会优先使用响应头中的 Content-Disposition 来确定文件的名称。如果后端返回的 Content-Disposition 头部中已经包含了 filename,浏览器会遵循这个头部中的文件名设置,而忽略 a.download 属性。
if (filename){
filename=decodeURIComponent(filename);// decodeURIComponent对名字进行解码()
encodeURIComponent()对URL进行编码
}
const blob = new Blob([res.data],
{type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
}); //文件类型
console.log(blob)
if (window.navigator.msSaveorOpenBlob){
navigator.msSaveBlob(blob,fileName);
}else{
const uri = window.URL.createobjectURL(blob);
const a = document.createElement('a');
a.href = uri;
a.download = fileName;
a.click();
window.URL.revokeobjectURL(uri);
}
}else{
console.error('Download failed:Response status =',res.status,res);
throw bufferToJson(res.data);
}
})
}catch (error){
console.error('Download failed with error:',error.message,error);
}
}
msSaveorOpenBlob,它是window.navigator对象的一个属性。该函数的作用是允许网页上的脚本在客户端直接触发一个“保存文件”的对话框,让用户能够将指定的二进制数据(Blob对象)保存到本地文件系统,通常默认保存到“下载”文件夹。与msSaveBlob除了提供保存选项外,还会根据用户的设置或选择,提供“打开”文件的选项,即直接用相应的应用程序打开文件而不是保存
第二种,封装好函数,直接传值的方法
第一步、写好下载文件流的函数
/**
*
*@param data blob的数据
*@param query 携带的请求参数
*/
export async function download(data){
console.log(data);
if (data){
const fileName decodeURIComponent(res.headers['content-disposition'].split('=')[1]);
if (filename){
filename=decodeURIComponent(filename);/decodeURIComponent对名字.进行解码encodeURIComponent()URL进行病码
const blob = new Blob([res.data],
{type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});// 文件类型
console.log(blob)
if (window.navigator.msSaveorOpenBlob){
navigator.msSaveBlob(blob,fileName);
}else{
const uri window.URL.createobjectURL(blob);
const a document.createElement('a');
a.href uri;
a.download fileName;
a.click();
window.URL.revokeobjectURL(uri);
}
}
}
第二步、在接口api那里加上 responseType:"blob"(一定的加上,必带的请求属性),
//下载结果
export function getDownloadResult(id){
return request({
url:baseUrl +`/taskbaseinfo/downloadResult?id=${id}`,
method:"get",
responseType:'blob'
})
}
第三步、调用接口 1.拿到blob数据之后,调用上面的download函数来处理文件
引入封装好的文件流函数 download
import {download} from 'xxxx'
const data = getDownloadResult(id)
download(data.data)
总结:当你可以下载但是excel表格显示损坏的时候,如下图
证明就是你在请求的时候没有带上 responseType:"blob" 要在请求api中带上