文章目录
<el-upload ref="fileUpload"
class="upload-demo"
action="upLoadingUrl"
:before-upload="beforeUpload"
:before-remove="beforeRemove"
:on-success="onSuccess"
:on-change="onchange"
:on-remove="onRemove"
:auto-upload="false"
:fileList="fileList"
:http-request="onUpload">
xxxx
</el-upload>
手动触发,用el-upload组件的this.$refs['fileUpload'].submit()
触发http-request
函数:
onUpload (file) {
console.log('onUpload-custom:file:', file)
let formData = new FormData()
formData.append(file.filename, file.file, file.file.name)
api.onUploadingFile(this.curCopyIds, formData).then(res => {
// xxx
})
},
或者手动执行http-request
函数:
click后,执行函数
// change的时候,存下来File
onchange (file, fileList) {
console.log('onchange',file,fileList)
this.fileContent = file // 记录file文件流内容
},
// 手动触发按钮,且不用this.$refs['fileUpload'].submit(),直接用自定义函数。
confirmImport () {
this.onUpload(this.fileContent)
},
上传报错
下载文件的时候,指定了文件类型为.xlsx,然后上传的时候报错。
"msg": "The supplied data appears to be in the OLE2 Format. You are calling the part of POI that deals with OOXML (Office Open XML) Documents. You need to call a different part of POI to process this data (eg HSSF instead of XSSF)",
接口中指定文件为.xls格式,所以 改为.xlsx可能破了文件内容(下载模版可以正常打开,格式也ok),但是上传会报错。 ⇒ 接口让 默认.xls即可,暂时不管.xlsx的。
下面这个使用了new Blob:
/**
* 下载模板
*/
async downloadTemp (e) {
e.stopPropagation()
let params = {}
let res = await deviceMappingDownloadTemp(params) // 获取到文件流
console.log('下载模版res:', res) // Blob
const blob = new Blob([res])
const blobUrl = window.URL.createObjectURL(blob)
let a = document.createElement('a')
a.download = `能源IOT设备映射批量导入模板.xls` // 不指定后缀的话,就是.txt的了。
a.href = blobUrl
a.click()
URL.revokeObjectURL(a.href) // 释放
// document.body.removeChild(a)
},
上面为什么要指定文件后缀?
接口返回的res是一个Blob
,为什么还需要new Blob
指定类型?
场景一:我们可以不要new Blob
,此时window.URL.createObjectURL(res)
,那么文件不指定文件类型即可。
场景二:如果 使用了new Blob
,默认就指定了类型(new Blob第二个参数就是指定类型的)
// 指定了blob类型,那么也可以不加后缀。
const blob = new Blob([res],{type:'application/vnd.ms-excel'})
const blobUrl = window.URL.createObjectURL(blob)
let a = document.createElement('a')
a.download = `能源IOT设备映射批量导入模板123`
Blob详解
Blob()
构造函数返回一个新的 Blob 对象。blob 的内容由参数数组中给出的值的串联组成。
var aBlob = new Blob( array, options );
const obj = {hello: 'world'};
const blob = new Blob(
[JSON.stringify(obj, null, 4)],
{type : 'application/json'}, // application/vnd.ms-excel
);
console.log('文件内容:',blob)
let blobUrl = URL.createObjectURL(blob)
let a = document.createElement('a')
a.download = `文件123`
a.href = blobUrl
a.click()
下载后是一个 json文件,内容为:
let obj = {
age: 18,
sex: '男'
}
let content = JSON.stringify(obj)
// blob类型
let blob = new Blob([content], {
type: 'application/json'
})
// 将blob转成url
let url = URL.createObjectURL(blob) //blob:null/244bec7f-e3d3-43d5-803e-f98cc5c8117f =>链接里面的数据就是右边的内容 {"age":18,"sex":"男"}
console.log(url)
// blob转file
let filename = '文件名'
let file = new File([blob], filename, {
type: 'application/json',
lastModified: Date.now()
});
// 或者
let file1 = new File([content], filename, {
type: 'application/json',
lastModified: Date.now()
});
console.log("文件", file, file1)
下面这个就是没有用new Blob,直接使用,所以download只指定名字即可,不用加后缀。
/**
* 下载错误日志
* 接口返回完整的URL:https://lfrz1.xxxx/abc.xls
* 直接window.open的话,文件名称是abc这种的,不友好。
* @param fileUrl
* @param fileName
*/
download (fileUrl, fileName) {
const url = fileUrl
let x = new XMLHttpRequest()
x.open('GET', url, true)
x.responseType = 'blob'
x.onload = function () {
console.log('日志res:', x.response) // Blob
let url = window.URL.createObjectURL(x.response)
let a = document.createElement('a')
a.href = url
a.download = fileName
a.click()
}
x.send()
},
// 调用
this.download(this.resultObj.downloadUrl, '错误日志')
Refused to get unsafe header “content-disposition”
后端接口返回文件流的时候,有文件名字,在headers里面,前端获取的时候报错:
Refused to get unsafe header "content-disposition"
//设置Access-Control-Expose-Headers避免前端调用获取Content-Disposition出现Refused to get unsafe header异常
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(FileBO.getFileName(), "UTF-8"));
// axios:
let dispositionStr = response.headers["content-disposition"];
// 或者 xhr:
xhr.getResponseHeader('content-disposition')
返回文件名是乱码,需要接口设置一下:
可能是:
response.setHeader("content-disposition","attachment;filename*=utf-8''" + URLEncoder.encode(fileName,"UTF-8"));
// 旧的做法
response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
// 新的做法
response.setHeader("content-disposition","attachment;filename*=utf-8''" + URLEncoder.encode(fileName,"UTF-8"));
参考:https://blog.csdn.net/fxtxz2/article/details/107334247
报错:Current request is not a multipart request
背景:手动上传,且通过axios封装接口(不用自己添加headers或者其他参数),但是报错了
报错:msg:“Current request is not a multipart request”
接口文档:
axios封装的默认content-type都是json的…所以el-upload使用axios封装的函数,也是json的,不符合要求啊,自己添加headers:
// 上传: TODO-todo
export const uploadDeviceAxios = params => {
return instance({
url: '/device/mgt/batchCreate/import',
method: 'post',
data: params,
headers: {
// 'Content-Type': 'multipart/form-data'
}
});
};
上传进度
https://juejin.cn/post/7265239806946590757
https://www.jb51.net/article/259304.htm
// 上传: TODO-todo
export const uploadDeviceAxios = params => {
return instance({
url: '/device/mgt/batchCreate/import',
method: 'post',
data: params,
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: (progressEvent) => {
console.log('上传e', progressEvent);
if (progressEvent.lengthComputable) {
console.log('进度:', Math.round((progressEvent.loaded / progressEvent.total) * 100));
}
}
});
};