如何修改GET请求以触发合法的文件附件响应(Django场景)
解决方案
一、后端视图实现(Django)
通过GET参数标记下载请求,结合Django的FileResponse和内存文件对象(避免磁盘IO)实现PGN文件下载:
- 导入必要模块:
import io import chess, chess.pgn from django.http import JsonResponse, HttpResponse, FileResponse
- 修改视图函数逻辑,新增下载分支:
def index(request, pgn_slug=None): board = chess.Board() game = chess.pgn.Game.from_board(board) game.headers["DrawOffered"] = "False" # 处理AJAX请求 if request.headers.get('x-requested-with') == 'XMLHttpRequest': response_obj = {} # 此处编写你的AJAX响应逻辑 return JsonResponse(response_obj) # 处理下载请求 elif request.GET.get('action') == 'download': # 生成PGN格式内容 pgn_content = str(game) # 用内存文件对象存储内容,无需写入磁盘 buffer = io.StringIO() buffer.write(pgn_content) buffer.seek(0) # 将文件指针移到开头,确保完整读取 # 返回附件响应 return FileResponse( buffer, as_attachment=True, filename='chess_game.pgn' # 自定义下载文件名 ) # 默认渲染页面 else: html = get_html(game, board) return HttpResponse(html)
二、前端触发逻辑
AJAX无法直接触发浏览器下载弹窗,我们构造带下载参数的URL,通过模拟a标签点击实现:
function downloadPGN(URL) { if (URL === undefined) { URL = window.location.href; } // 构造带下载参数的URL const downloadUrl = new URL(URL); downloadUrl.searchParams.set('action', 'download'); // 模拟a标签点击触发下载 const a = document.createElement('a'); a.href = downloadUrl.toString(); a.style.display = 'none'; document.body.appendChild(a); a.click(); document.body.removeChild(a); }
按钮代码保持不变:
<button type="button" id="downloadButton" onClick="downloadPGN()">↓</button>
关键细节说明
- 请求标记方式:用
action=downloadGET参数,比自定义请求头更直观,前端构造简单。 - 内存文件对象:使用
io.StringIO代替物理文件,避免磁盘操作,无需清理临时文件。 - FileResponse优势:Django的
FileResponse专门处理文件流响应,自动设置HTTP头确保浏览器识别为附件下载。
内容的提问来源于stack exchange,提问作者dig dug
相关产品推荐
相关产品推荐

