使用axios上传文件

时间:2018-03-20 10:54:51

标签: django api file django-rest-framework axios

您好我正在尝试将文件上传到服务器,但我发送文件时遇到了困难。我在后端使用Django,我已经设置了一个允许用户发送文件的put端点,我确认它使用邮递员按预期工作。但是,我在前端上传时遇到问题。所以这就是我的代码在前端的样子。

selectFileManually.addEventListener('change', function(event){
    event.stopPropagation();
    event.preventDefault();
            axios.put('http://127.0.0.1:8000/api/v1/fileupload/', {
                file: this.files[0]
            }).then(resp => console.log(resp.data)).catch(err => console.log(err.response.data))
        }
    }
})

此处selectFileManuallyinput[type='file']。但是,当我发送此请求时,服务器返回时出现以下错误:"Missing filename. Request should include a Content-Disposition header with a filename parameter当我查看有效负载时,它完全为空:“{file:{}}”即使您可以清楚地看到我提供了一个文件发送。这就是我的代码在后端看到的方式

# views.py
from django.shortcuts import render
from rest_framework.views import APIView 
from rest_framework.response import Response 
from rest_framework.parsers import FileUploadParser, MultiPartParser
import os

# Create your views here.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

class FileUploadView(APIView):
    parser_classes = (MultiPartParser, FileUploadParser, )

    def put(self, request, format=None):
        print(request.data)
        with open(os.path.join(BASE_DIR, 'api/media', request.data['file'].name), 'wb') as f:
            for chunk in request.data['file'].chunks():
                f.write(chunk)
        return Response(status=204) 




#urls.py 
from django.urls import path 
from . import views 

urlpatterns = [
    path('fileupload/', views.FileUploadView.as_view()),
]

请有人帮助我。我知道this.files [0]不是空的,因为控制台记录了文件,它告诉我它确实是正确的内容

1 个答案:

答案 0 :(得分:1)

根据docs,您需要为视图指定文件名参数以处理请求。这可以通过两种方式完成:

<强> 1。可以使用文件名URL关键字参数调用视图,然后将该参数设置为文件名。要实现此目的,您需要将网址模式更改为

urlpatterns = [
    path('fileupload/(?P<filename>[^/]+)$', views.FileUploadView.as_view()),
]

<强> 2。如果在没有文件名URL关键字参数的情况下调用视图,则客户端必须在 Content-Disposition HTTP标头中设置它。然后由视图中的FileUploadParser处理。 / p>

例如Content-Disposition: attachment; filename=image.jpg.

无论哪种方式,您都需要在发出请求时访问文件名。 在您的情况下,由于您的网址格式不包含文件名参数,因此您需要设置标题以包含 Content-Disposition

假设this.files[0]是一个fileObject,只需执行this.files[0].name即可获得文件名。现在在axios请求上设置标题,因此您的前端代码应如下所示。

selectFileManually.addEventListener('change', function(event){    
    event.stopPropagation();
    event.preventDefault();
            axios.put('http://127.0.0.1:8000/api/v1/fileupload/', {
                file: this.files[0]
            },{headers:{
                         'Content-Disposition': 'attachment; filename=this.files[0].name'
                      }
              },
    ).then(resp => console.log(resp.data)).catch(err => console.log(err.response.data))
        }
    }
})

希望这有帮助!