python 代码
def post(self, request):
'''下载文件'''
# 获取请求体中原始的JSON数据
json_str = request.body
# 使用json模块将原始的JSON数据转字典
json_dict = json.loads(json_str)
masterorder_id = json_dict.get('masterorder_id')
filepath = json_dict.get('filepath')
try:
# obj_master = MasterOrder.objects.get(id=masterorder_id)
# if eval(obj_master.filepath):
# for path in eval(obj_master.filepath):
filename = os.path.basename(filepath)
file = open(filepath, 'rb')
response = FileResponse(file)
response['Content-Type'] = 'application/octet-stream'
response['Access-Control-Expose-Headers'] = "Content-Disposition, Content-Type"
response['Content-Disposition'] = 'attachment;filename={}'.format(escape_uri_path(filename)) # 解决中文乱码问题
return response
except Exception as e:
return JsonResponse(
{'code': 1, 'error': "Failed to submit text, the specific reason:" + str(e)})
async startdownloadFile(info) {
await axios
.post(
this.baseUrl + "/task/orderinfo/",
{
//如果没有要传给后台的数据这里可以为空,但最好留着这个花括号,不然后台可能将response当做数据
masterorder_id: info.master_id,
},
{
responseType: "blob",
},
{
headers: {
"Content-Type": "application/json;charset=UTF-8",
},
}
)
.then((response) => {
//headers请求头的乱码数据转换为中文
const fileName = decodeURI(
response.headers['content-disposition'].split(';')[1].split('=')[1]
);
//下载文件
let blob = new Blob([response.data], {
type: "application/octet-stream",
});
let objectUrl = URL.createObjectURL(blob); // 创建URL
const link = document.createElement("a");
link.href = objectUrl;
// link.download = '.xlsx'// 自定义文件名
//这里是获取后台传过来的文件名
link.setAttribute("download", fileName);
link.click(); // 下载文件
URL.revokeObjectURL(objectUrl); // 释放内存
})
.catch((error) => {
console.log(error);
alert("下载失败");
});
},
有可能会出现跨域问题(拿不到filename)
有两种解决方案,一种是前端做代理,二种是后端做处理
后端:
产生问题原因
跨域(CORS)请求中,被axios封装好的XMLHttpRequest对象中的方法getResponseHeader()默认只能获取6个基本的字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。因此,需要获取其他的属性,需要后端在响应的时候去在Access-Control-Expose-Headers中指定content-disposition属性。
所以这是一个后端的锅,是他没有配置,这个问题去找后端,让他在response中配置放行。
response['Access-Control-Expose-Headers'] = "Content-Disposition, Content-Type"
前端
baseUrl: "http://localhost:8080/api" # 这是前端服务
devServer: {
proxy: {
'/api': {
context: ['/api'], # 接口的统一前缀
target: 'http://172.16.10.x:8000' # 这是请求后端接口
},
}
},