Django Rest Framework:通过 AJAX 上传文件

Posted

技术标签:

【中文标题】Django Rest Framework:通过 AJAX 上传文件【英文标题】:Django Rest Framework: Upload file via AJAX 【发布时间】:2015-11-29 22:31:17 【问题描述】:

我有一个视图和序列化器:

class UserView(generics.RetrieveUpdateAPIView):
    model = get_user_model()
    serializer_class = UserProfileSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_object(self, *args, **kwargs):
        return self.request.user


class UserImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()
        fields = ('image',)

它们与 httpie 配合得很好:

http -f put localhost:8000/accounts/api/image/ "Authorization: Token mytoken" image@~/Downloads/test.jpg
HTTP/1.0 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Date: Thu, 03 Sep 2015 22:50:33 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Vary: Accept
X-Frame-Options: SAMEORIGIN


    "image": "http://localhost:8000/media/accounts/user_images/test.jpg"

我的图片已上传并显示在管理员中。

现在我希望能够使用 AJAX 上传文件,但它显然不想工作:

<form action="http://localhost:8000/accounts/api/image/"
      method="put"
      enctype="multipart/form-data">
    <input name="image" type="file">
    <input type="submit">
</form>

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<script>
    $('form').submit(function(e) 
        var formData = new FormData($(this));
        $.ajax(
            url: $(this).attr('action'),
            type: $(this).attr('method'),
            data: formData,
            headers: 'Authorization': 'Token mytoken',
            cache: false,
            contentType: false,
            processData: false,
            success: function()  alert('it works') ,
        );
        e.preventDefault();
    );
</script>

现在,我的“它有效”警报出现了。我知道表单正在提交到正确的位置,我可以在 Django 开发服务器中看到它被请求为 PUT 并且它以 200 响应(与 httpie 的响应相同):

[03/Sep/2015 22:47:23] "PUT /accounts/api/image/ HTTP/1.1" 200 77

但文件似乎没有上传,也没有显示在管理中。

我没有想法。

【问题讨论】:

我认为您可能发送了错误的内容类型。根据api.jquery.com/jquery.ajax/#jQuery-ajax-settings,你应该指定contentType: 'multipart/form-data'上传文件。 @dukebody,我很快就试过了,但它给了我一个 400 Bad Request 并出现此错误:detail: "Multipart form parse error - Invalid boundary in multipart: None" 对不起,我错了。见***.com/questions/9622901/… 和***.com/questions/2320069/jquery-ajax-file-upload 【参考方案1】:

好的,我无法准确解释原因,但似乎单独使用 var formData = new FormData($(this)); 是不够的,需要明确附加,原因是什么?如果有人可以解释,请做。

工作代码:

<form action="http://localhost:8000/accounts/api/image/"
      method="put"
      enctype="multipart/form-data">
    <input name="image" type="file" id="image">
    <input type="submit">
</form>

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<script>
    $('form').submit(function(e) 
        var formData = new FormData($(this));
        formData.append('image', $('#image')[0].files[0]);
        $.ajax(
            url: $(this).attr('action'),
            type: $(this).attr('method'),
            data: formData,
            headers: 'Authorization': 'Token mytoken',
            cache: false,
            contentType: false,
            processData: false,
            success: function()  alert('it works') ,
        );
        e.preventDefault();
    );
</script>

【讨论】:

FormData 在其构造函数中需要非 jQuery 对象。如果你像这样var formData = new FormData($(this)[0]); 初始化你的formData,它应该被正确初始化,然后你不需要在下一行追加。 $(this)[0] == this

以上是关于Django Rest Framework:通过 AJAX 上传文件的主要内容,如果未能解决你的问题,请参考以下文章

Django rest framework 之版本

如何通过 Django Rest Framework 返回嵌套的 json

请教Django REST framework的一些问题

记录对 django-rest-framework 的请求

Django - 如何通过 API 端点使用 rest_framework 动态地将多个对象添加到数据库中

优化Django Rest Framework 的Token验证功能