You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:47:04