Django环境下Ajax下载文件文件名变为随机字符串的问题
问题描述
在Django环境中用Ajax实现文件下载,功能能正常运行,但下载后的文件名是一串8位随机字符,每次下载都会变化。后端逻辑看起来没问题,相关代码如下:
JS/HTML代码
<script> function downloadFile(){ var filename = 'data.txt'; $.ajax({ url: 'downloadFile', data: {'filename': filename}, success: function(blob, status, xhr){ var disposition = xhr.getResponseHeader('Content-Disposition'); if (disposition && disposition.indexOf('attachment') != -1){ var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; var matches = filenameRegex.exec(disposition); if (matches != null && matches[1]){ filename = matches[1].replace(/['"]/g,''); } } var bd = []; bd.push(blob); var typename = "application/" + filename; var downloadURL = window.URL.createObjectURL(new Blob(bd, {type: typename})); var a = document.createElement("a"); a.href = downloadURL; document.body.append(a); a.click(); } }); } </script> <button id="downloadFile" type="button" onclick="downloadFile()"><i class="fa fa-download"></i></button>
Django views.py代码
import pathlib import os def downloadFile(request): fname = request.GET.get('filename') fpath = os.path.join(<local_filesystem_path>, fname) # code to generate file here if pathlib.Path(fpath).exists(): file_download = open(fpath, 'rb') response = HttpResponse(file_download, content_type='application/{}'.format(fname)) response['Content-Disposition'] = 'attachment; filename="{}"'.format(fname) return response
Django urls.py代码
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), path('downloadFile', views.downloadFile, name='downloadFile') ]
怀疑是浏览器认为文件名未设置,因此分配了随机字符串,请问如何设置自定义文件名?
解决方案
问题出在前端创建的<a>标签缺少download属性,浏览器无法识别指定文件名,因此自动生成随机字符串。
修改JS代码中创建<a>标签的部分,添加download属性并赋值为解析后的文件名即可:
var a = document.createElement("a"); a.href = downloadURL; a.download = filename; // 新增这一行,指定下载时的文件名 document.body.append(a); a.click();
另外可以优化两点:
- 创建Blob时,
typename的写法不规范,不要用application/拼接文件名,文本文件可直接用text/plain,不确定文件类型的话,用application/octet-stream让浏览器自动处理:
var downloadURL = window.URL.createObjectURL(new Blob(bd, {type: 'application/octet-stream'}));
- 后端的
content_type建议改成对应文件的正确类型,比如文本文件用text/plain,避免application/{}'.format(fname)这种不标准的写法。
内容的提问来源于stack exchange,提问作者asdf
相关产品推荐
相关产品推荐

