使用Django+Pillow生成图片后无法触发下载的问题求助
问题原因
浏览器不会自动处理Ajax请求返回的Content-Disposition: attachment头——Ajax的设计是异步获取数据而非触发浏览器的下载行为,所以即使后端正确返回了图片,也需要前端手动将二进制数据转换为可下载资源。
解决方案
- 前端Ajax请求需指定接收二进制
blob类型数据,而非json(因为返回的是图片二进制,不是JSON格式) - 在请求成功回调中,将返回的Blob数据转换为临时URL,通过创建隐藏的
<a>标签模拟点击来触发下载 - 下载完成后清理临时URL,避免内存泄漏
修正后的代码
前端Ajax代码
function downloadDoa(){ allDoas = [] for (let i = 0; i < userDoaAll.length; i++) { userCustomMadeDoa = userDoaAll[i]; if (userCustomMadeDoa.classList.contains("customUserDoa")){ allDoas.push(['na',userCustomMadeDoa.innerHTML]) } } console.log(allDoas) $.ajax({ url: "{% url 'api:download_doa' %}", data: { customDoasLists: JSON.stringify(allDoas), csrfmiddlewaretoken: '{{ csrf_token }}', }, method : "post", dataType : "blob", // 改为接收blob类型 headers: {'X-CSRFToken': csrftoken}, success: function (response) { // 创建临时URL const url = window.URL.createObjectURL(response); // 创建a标签 const a = document.createElement('a'); a.href = url; a.download = 'file_name.png'; // 指定下载文件名 document.body.appendChild(a); // 模拟点击 a.click(); // 清理资源 document.body.removeChild(a); window.URL.revokeObjectURL(url); }, }); }
后端代码优化(可选)
调整Content-Disposition头的引号格式,避免转义问题:
@api.post("/download_doa",url_name="download_doa",auth=None) def download_doa(request): im_io = io.BytesIO() text_list = json.loads(request.POST.get('customDoasLists')) font_path_a = "Hafs.ttf" font_path_na = "Arial.ttf" font_size_a = 40 font_size_na = 30 text_color = (0, 0, 0) # RGB color (black) background_color = (255, 255, 255, 255) # RGBA color (white) output_image = text_to_image(text_list, font_path_a, font_size_a,font_path_na, font_size_na, text_color, background_color) output_image.save(im_io, 'png') im_io.seek(0) return HttpResponse( im_io, headers={ 'Content-Type': 'image/png', # 调整引号格式,或直接省略引号 'Content-Disposition': 'attachment;filename=file_name.png' } )
关键修改说明
dataType: "blob":告诉jQuery接收二进制Blob数据,而非尝试解析为JSON- 临时URL处理:通过
URL.createObjectURL将Blob转换为浏览器可识别的资源URL,模拟a标签点击触发下载 - 资源清理:下载完成后移除临时a标签并释放URL,防止内存泄漏
内容的提问来源于stack exchange,提问作者Hazqeel Afyq
相关产品推荐
相关产品推荐

