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

通过Ajax向Django传输文件时的CSRF与参数配置问题

解决AJAX上传文件时携带CSRF Token的问题

这个问题我在处理Django项目的文件上传时也碰到过,核心矛盾在于:上传文件必须使用multipart/form-data格式,这要求我们把processData和contentType设为false,但这会导致默认的CSRF Token传递方式失效。下面给你两种可行的解决方案,都是基于FormData来实现的:

方案一:把CSRF Token直接加入FormData对象

这是最直观的方式,将文件、普通表单数据和CSRF Token一起打包到FormData里,让AJAX请求自然携带所有数据:

完整代码示例

$(document).ready(function(){
    // 你已有的获取CSRF Token的函数,这是Django官方推荐的方法,完全可行
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // 检查cookie是否以目标名称开头
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    // 假设上传触发事件是点击某个按钮
    $('#upload-btn').click(function(e){
        e.preventDefault();
        
        // 获取CSRF Token
        var csrftoken = getCookie('csrftoken');
        
        // 创建FormData对象,用来包装文件和表单数据
        var formData = new FormData();
        
        // 添加文件(这里假设你的文件输入框id是file-input)
        formData.append('file', $('#file-input')[0].files[0]);
        
        // 如果有其他普通表单字段,也一起加进去
        formData.append('username', $('#username-input').val());
        formData.append('description', $('#desc-input').val());
        
        // 关键步骤:把CSRF Token加入FormData
        formData.append('csrfmiddlewaretoken', csrftoken);
        
        // 发起AJAX请求
        $.ajax({
            url: '/your-upload-endpoint/',  // 替换成你的后端上传接口
            type: 'POST',
            data: formData,
            processData: false,  // 必须设为false,禁止jQuery处理FormData(否则文件会被转成字符串损坏)
            contentType: false,  // 必须设为false,让浏览器自动生成正确的multipart/form-data请求头
            success: function(response){
                console.log('文件上传成功!', response);
                // 这里可以添加上传成功后的逻辑,比如刷新页面或提示用户
            },
            error: function(xhr, status, error){
                console.error('上传失败:', error);
                // 处理错误情况
            }
        });
    });
});

方案二:通过请求头传递CSRF Token

如果你不想把Token加到FormData里,也可以通过请求头X-CSRFToken来传递,Django的CSRF中间件同样会识别这个请求头:

关键代码修改

只需要修改AJAX的配置部分,去掉FormData里的Token,添加headers配置即可:

$.ajax({
    url: '/your-upload-endpoint/',
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    // 添加请求头传递CSRF Token
    headers: {
        'X-CSRFToken': csrftoken
    },
    success: function(response){
        // 成功逻辑
    },
    error: function(xhr, status, error){
        // 错误逻辑
    }
});

注意事项

  1. 确保你的Django后端视图正确处理文件上传:需要用request.FILES.get('file')来获取上传的文件,并且不需要给视图加@csrf_exempt装饰器——只要正确传递了CSRF Token,就能通过默认的CSRF保护。
  2. 如果是直接用表单提交,记得给表单加上enctype="multipart/form-data"属性,但用AJAX+FormData的话,这个属性不是必须的,浏览器会自动处理。
  3. 确认getCookie函数能正确获取到csrftoken Cookie,Django默认的Cookie名称就是csrftoken,除非你在settings里修改过CSRF_COOKIE_NAME。

内容的提问来源于stack exchange,提问作者Federico Ribero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:04:06