Django通过Ajax调用无法下载查询生成的CSV文件求助
解决Django中Ajax调用下载CSV文件无效的问题
Ajax请求本身不会触发浏览器的下载行为——它仅用于获取数据,浏览器不会自动处理带有Content-Disposition: attachment的响应,这就是你遇到问题的核心原因。以下是两种可行的解决方案:
方案一:用表单提交替代Ajax(推荐)
直接通过动态创建表单并提交,利用浏览器原生机制处理下载,兼容性更好:
function Download(ser_no){ // 创建隐藏表单 const form = document.createElement('form'); form.method = 'POST'; form.action = '{% url "beacon_server:download_rollback" %}'; // 添加serial字段 const serialInput = document.createElement('input'); serialInput.type = 'hidden'; serialInput.name = 'serial'; serialInput.value = ser_no; // 添加CSRF Token const csrfInput = document.createElement('input'); csrfInput.type = 'hidden'; csrfInput.name = 'csrfmiddlewaretoken'; csrfInput.value = $('input[name=csrfmiddlewaretoken]').val(); // 添加其他必要字段 const typeInput = document.createElement('input'); typeInput.type = 'hidden'; typeInput.name = 'type'; typeInput.value = 'Download'; const actionInput = document.createElement('input'); actionInput.type = 'hidden'; actionInput.name = 'action'; actionInput.value = 'post'; // 挂载表单并提交 form.appendChild(serialInput); form.appendChild(csrfInput); form.appendChild(typeInput); form.appendChild(actionInput); document.body.appendChild(form); form.submit(); document.body.removeChild(form); }
方案二:Ajax成功后手动触发下载
如果必须保留Ajax请求,可在回调中处理返回的CSV内容,手动创建下载链接:
function Download(ser_no){ console.log('AJAX'); $.ajax({ type: 'POST', url: '{% url "beacon_server:download_rollback" %}', data: { serial: ser_no, type: "Download", csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(), action: 'post' }, dataType: 'text', // 禁用自动解析,获取原始CSV文本 success: function (csvContent) { // 创建Blob对象存储CSV内容 const blob = new Blob([csvContent], { type: 'text/csv' }); const downloadUrl = window.URL.createObjectURL(blob); // 创建临时a标签触发下载 const aTag = document.createElement('a'); aTag.href = downloadUrl; aTag.download = `${ser_no}.csv`; document.body.appendChild(aTag); aTag.click(); // 清理资源 window.URL.revokeObjectURL(downloadUrl); document.body.removeChild(aTag); }, error: function (xhr,errmsg,err) { console.error('下载失败:', errmsg); } }); }
额外优化:修正Django视图的响应头
原视图中Content-Disposition的HTML实体引号可以简化,避免潜在问题:
def download_rollback(request): serial = request.POST.get('serial') response = HttpResponse(content_type='text/csv') # 直接使用双引号,无需HTML实体转义 response['Content-Disposition'] = f'attachment; filename="{serial}.csv"' writer = csv.writer(response) writer.writerow(['timestamp','serial','log']) queryset = ConfigLog.objects.filter(ser_no=serial).filter(log__contains='ROLLBACK') for obj in queryset: writer.writerow([obj.timestamp, obj.ser_no, obj.log]) return response
内容的提问来源于stack exchange,提问作者Rupert
相关产品推荐
相关产品推荐

