当前位置:   article > 正文

使用axios实现文件流下载的安全问题_axios拦截器下载

axios拦截器下载

为什么要使用axios来下载文件?
这涉及到安全问题,我们平时下载文件,一般都是使用window.location.href来实现,即我们打开网站,只要输入对应的下载接口都可以实现下载。
例如:https://www.baidu.com?id=123,别人运用爬虫修改id的值,就可以获取到服务器的所有下载数据,因此我们需要加上一些权限校验

安全方式

安全方式我们考虑了几种实现方式(总体来说权限校验的重点还是token)

  • 对id进行加密处理(id+token加密),还是采用window.location.href实现
    • 优势:还是使用浏览器下载 ,对于文件没有大小限制
  • 采用axios,请求头带上token
    • 优势:简单,统一的请求风格,只实用于下载较小文件

对id进行加密处理

这个就属于后端处理了,实现原理如下
后端把id+token+时间戳进行加密处理 => 前端采用get请求(window.location.href)=> 后端对id进行解密,校验时间戳/token/id三个参数 => 回调

请求头带上token

我们选择请求头带上token,代码如下:

axios({
	method: 'get',// 设置请求方式
	url: process.env.VUE_APP_CURRENTMODE + downloadUrl + record.id,// 设置请求地址
	headers: {// 设置请求头
		Authorization: this.$store.getters[`${this.accountType}AuthToken`] || this.$store.getters['baseAuthToken'] || 'xxxx'
	},
	responseType: 'blob'// 设置相应数据的类型,设置后后台返回的数据会被强制转为blob类型;如果后台返回代表失败的data,前端也无法得知,依然会下载得到名为undefined的文件。
}).then(function (res) {
	let url = window.URL.createObjectURL(new Blob([res.data]))
	let link = document.createElement('a')
	link.style.display = 'none'
	link.href = url
	link.setAttribute('download', record.name)//设置下载文件名称,否则会得到undefined的文件
	document.body.appendChild(link)
	console.log(res)
	link.click()
	link = null //销毁
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

当我们使用axios的时候,回调并不会自动下载

  • 为什么axios没有办法实现下载功能?

    因为浏览器的GET(frame、a)和POST(form)请求具有如下特点:

    • response会交由浏览器处理
    • response内容可以为二进制文件、字符串等

    axios是请求具有如下特点:

    • response会交由Javascript处理
    • response内容仅可以为字符串 因此,axios本身无法触发浏览器的下载功能。

因此此处借助a标签来实现下载功能

拓展:

还有更优美的写法,我们可以在axios成功回调中(也可以是axios拦截器,主要看如何封装请求的),判断返回的response如果是文件流,则我们可以创建a标签实现下载。

代码如下:

import axios from 'axios'
 
const downloadBlob = (res,fileName) => {
	let url =  window.URL.createObjectURL(new Blob([res.data]))
	let link = document.createElement('a')
	link.style.display = 'none'
	link.href = url
	link.setAttribute('download', fileName)//设置下载文件名称,否则会得到undefined的文件
	document.body.appendChild(link)
	console.log(res)
	link.click()
	link = null //销毁
}
 
const fetch = (apiName, data = {}, fetchConfigParams = {}) => {
	...
	axios({
		timeout: fetchConfig.timeout,
		url: _url,
		method: fetchConfig.method,
		headers,
		responseType: fetchConfig.responseType,
		crossDomain: true,
		xhrFields: {
			withCredentials: true
		},
		data: {
			plain: data
		},
		...mockOptions
	}).then(res => {
		const authToken = res.headers.authorization
		if (res.status == config.successCode) {
			try {
				if (res.headers && (res.headers['content-type'] === 'application/x-msdownload' || res.headers['content-type'] === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')) {
				   	downloadBlob(res,data.fileName)
				    res.data='';
				    res.headers['content-type'] = 'text/json'
				    res.code = 200
				    resolve(res);
				 }
				 ...
			} 
			...
	})
}

export default {
	fetch
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/227773?site
推荐阅读
相关标签
  

闽ICP备14008679号