简体   繁体   English

如何将文件从 React 发送到 Django REST Framework?

[英]How to send files to Django REST Framework from React?

I need to send arbitrary (eg xls ) files from React-based frontend to Django REST Framework backend.我需要将任意(例如xls )文件从基于 React 的前端发送到 Django REST Framework 后端。

Googled and tried many code variants for couple of hours, none of them worked completely.谷歌搜索并尝试了几个小时的许多代码变体,但没有一个完全有效。

Here are essential parts of code:以下是代码的重要部分:

  1. React反应

1.1 Form input field 1.1 表单输入字段

<input
    type="file"
    multiple={true}
    accept=".xls,.xlsx,.csv,.txt"
    onChange={this.handleFilesChosen}
/>

1.2 handleFilesChosen 1.2 handleFilesChosen

    handleFilesChosen = event => {
        this.setState({
            files: event.target.files
        });
    }

1.3 Upload click handler ( authHeader is function substituting Authorization Bearer token) 1.3 上传点击处理程序( authHeader是代替 Authorization Bearer token 的函数)

    handleUploadClick = event => {
        let formData = new FormData();
        for (let file of this.state.files) {
            formData.append('files', file);
        }
        const csrf = this.getCookie('csrftoken');
        fetch(`${API_BASE_PATH}/load-input-data/`, {
            method: 'POST',
            headers: authHeader({contentType: 'multipart/form-data', csrf: csrf}),
            body: formData,
        })
        .then(result => result.json())
        .catch(error => error);
    }
  1. DRF View DRF 视图
class LoadInputDataView(APIView):
    parser_class = (MultiPartParser,)

    @method_decorator(login_required)
    def post(self, request, format=None):
        print(request.data)
        return Response(status=status.HTTP_201_CREATED)

I selected simple txt file (to make debugging easy, binary will go later) with hello world content, uploaded it and get <QueryDict: {}> in Django runserver console.我选择了简单的txt文件(使调试容易,双星将在稍后去)与hello world内容,上传,并得到<QueryDict: {}>在Django runserver控制台。

If I look at Chrome network tab, I see following empty request payload instead of real file content:如果我查看 Chrome 网络选项卡,我会看到以下空请求负载而不是实际文件内容:

------WebKitFormBoundaryYw6ABRFkvxatzHqi
Content-Disposition: form-data; name="files"; filename="foo.txt"
Content-Type: text/plain


------WebKitFormBoundaryYw6ABRFkvxatzHqi--

Tried to remove contentType header - got 400 error with message JSON parse error (browser substitutes JSON contentType header automatically).试图删除contentType标头 - 出现 400 错误,消息JSON parse error (浏览器自动替换 JSON contentType 标头)。

I'm stuck.我被困住了。 Could anybody guide me?有人可以指导我吗?

Found solution.找到解决方案。 I should not set Content-Type header manually, it is set automatically with boundary option.我不应该手动设置Content-Type标头,它是使用boundary选项自动设置的。 Now Django's request.FILES work too and I could work with uploaded files from backend using code like:现在 Django 的request.FILES也可以工作了,我可以使用如下代码处理从后端上传的文件:

class ParseInputDataView(APIView):
    parser_class = (MultiPartParser,)
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, controller_id, format=None):
        for file_entry in request.FILES.getlist('files'):
            uploaded_file_name = file_entry.name
            uploaded_file_content = file_entry.read()
            ...

I decided to maintain uniformity in the API and send the image within JSON.我决定在 API 中保持一致性并在 JSON 中发送图像。

In React:在反应中:

const [image, setImage] = useState(null);

  const handleImageChange = (e) => {
    e.preventDefault();
    const reader = new FileReader();
    reader.onload = () => {
      var blocks = reader.result.split(";");
      const realData = blocks[1].split(",")[1];
      setImage(realData);
    };
    reader.onerror = (error) => console.error(error);
    reader.readAsDataURL(e.target.files[0]);
  };

 const onSaveHandler = () => {
    fetch(`/url`, {
        method: "post",
        credentials: "include", // send cookie with auth
        headers: {
            "Content-Type": "application/json",
            "X-CSRFToken": document.getElementById("csrf-token").value,
        }
        body: JSON.stringify({imageData: image}),
     });
 }

return(
 <div>
      <input
        onChange={handleImageChange}
        id="logo"
        type="file"
        multiple="false"
        accept="image/*"
      />
      <button onClick={onSaveHandler}>
        SAVE
      </button>
 </div>);

In Django (DRF):在 Django (DRF) 中:

class CustomerViewSet(viewsets.ModelViewSet):
      # override create method
      def create(self, request, *args, **kwargs):
        image_path = "whatever.jpg"
        print('save image on disk: ' + image_path)
        with open(image_path, "wb") as fh:
            fh.write(base64.b64decode(request.data.get("imageData")))
        return super().create(request)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 Axios 将 CSRF Coo​​kie 从 React 发送到 Django Rest Framework - How to send CSRF Cookie from React to Django Rest Framework with Axios 如何使用 Rest 框架从前端(React)发送查询到 Django - How to send a query from the frontend (React) to Django with Rest Framework 如何使用django-rest-framework和React从django发送密码重置电子邮件 - How to send password reset email from django using django-rest-framework and React 如何在 React 中显示来自 django-rest-framework 的错误消息 - How to display error messages from django-rest-framework in React 图像未从 django rest 框架加载 - Image is not loading from django rest framework in react 从反应发送数据到 django rest api - send Data from react to django rest api 如何使用 react 和 axios 将 GET 请求 header 中的数据发送到 Django rest 框架? - how to send data in GET request header using react and axios to Django rest framework? 如何在 AWS 上部署 Django Rest Framework 和 React - How to Deploy Django Rest Framework and React on AWS 无法使用React JS将文件上传到Django Rest框架 - cannot upload files to django rest framework using react js 从 django 到 django rest 框架:电子商务与反应 - from django to django rest framework : e-commerce with react
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM