前提:利用接口导出一个文件,前端会遇到的几种情况。这里主要记录一下文件流太大的情况
1. 导出接口直接给的文件流
- 文件不大的时候,我们直接使用a标签交给浏览器来下载
function downOSSUrl(url) {
const a = document.createElement('a')
a.href = url
a.rel = 'noreferrer'
document.body.appendChild(a)
a.click()
a.remove()
}
- 文件大的时候,直接使用以上方式就不太合适,接口处理太慢了,点击后页面没啥反应,还以为有bug。那就获取状态加个loading吧
// request 是封装的axios。 主要是注明一下 responseType: 'blob'
this.exportLoading = true
request({ url:'exportURL', params, responseType: 'blob' }).then(res => {
this.exportLoading = false
if (res === 0) {
this.$message.warning(提示语)
}
}).catch(() => {
this.exportLoading = false
})
拦截一下axios。 下面的链接超时时间timeout以及nginx的超时时间我们都改大一些
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
timeout: 300000 // request timeout
})
service.interceptors.response.use(
response => {
if (response.config.responseType === 'blob' && response.status === 200) {
if (response.data.size === 0) {
return 0
}
const filename = response.headers['content-disposition'].split(';')[1].split('=')[1]
const blob = new Blob([response.data])
const downloadElement = document.createElement('a')
const href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = filename // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉blob对象
return
}
}
)
以上代码可以看到两个点
(1)response.data.size 长度为0 ,我这里直接返回0.
因为后端考虑到处理时间太长,机器负载问题,限制了一分钟内不能同时多次下载,直接抛错。当多次请求到后端时体现在接口返回内容上,流的长度就是0,此时提示用户:稍后再试
(2)当有信息的时候呢,那就是有两种情况。
一种是包含错误信息或者提示信息, 一种是真正的文件信息。上面代码只考虑了直接下载文件信息。
当和后端有约定要展示特定条件的提示信息时,可以增加以下判断。将流用 filereader
解析程json
if(response.headers['content-type'].includes('json')){
const fileReader = new FileReader()
fileReader.readAsText(response.data, 'utf-8')
fileReader.onload = function(res){
....
}
}
(3) 文件名从响应头中的content-disposition拿到,没有的话,要后端导出
其实相比于直接用
a
标签交给浏览器下载,这样的请求后下载的,是直接写入到浏览器内存的,所以可以看到整个请求也包含了download
的时间,再到磁盘,才会在浏览器上看到进入了下载中心
2. 导出接口给的是有正常响应体,result
是oss地址
,那拿到地址后再直接去a标签
下载即可
3. 接口处理时间太长,出现504 gateway time-out
,很明显nginx
太久没拿到服务端结果,给了前端504
。 设置nginx
代理响应时间
(1)上面有个
axios
请求超时的时间,以毫秒为单位。设置大点,这里超时是主动断开了,但是后端还在处理。
(2)nginx 设置超时时间,单位是秒。可以设置在http
全局模块,server
模块,或者是location
特定模块。
location /api {
proxy_read_timeout 300; // 代理读取超时时间
proxy_send_timeout 300; // 代理发送超时时间
proxy_connect_timeout 300; // 代理连接超时时间
}
网友评论