简体   繁体   中英

Send File via Fetch to Django REST Endpoint?

I'm trying to upload a file via Fetch, to a Django REST endpoint.

Component with Fetch Code:

function myComponent(props) {
  const classes = useStyles();
  const [{token}] = useContext();

  function handleImageUpload(files) {
    let formData = new FormData()
    formData.append('file', files[0])

    fetch(receiveSpreadsheetEndpoint, {
      method: 'POST',
      body: formData,
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
      },
    })
      .then(response => response.json())
      .then(data => {
        console.log(data)
      })
      .catch(error => {
        console.error(error)
      })
  }

  function Dropzone(props) {
    const [files, setFiles] = useState([]);

    function handleChange(event) {
      setFiles(event[0]);
    }

    return (
      <>
        <DropzoneArea
          onChange={event => handleChange(event)}
        />

        <Button
          variant="contained"
          color="primary"
          onClick={event => handleImageUpload([files])}
        >
          Primary
        </Button>
      </>
    )
  }

  return (
    <Container className={classes.root} height="100%">
      <Dropzone
        acceptedFiles={['.csv', 'text/*', 'text/csv']}
        showPreviews={true}
        showFileNamesInPreview={true}
      />

    </Container>
  );
}

Django REST endpoint:

class ReceiveFileData(APIView):
    permission_classes = (IsAuthenticated,)
    parser_classes = (JSONParser, FormParser, MultiPartParser)

    def post(self, request):
        my_file = request.stream.read 

        data = {} <== a breakpoint is set here
        return Response(data, status=status.HTTP_200_OK)

After my_file = request.stream.read , my_file contains b'' .

What am I leaving out?

UPDATE

Here's the request object when it arrives at the REST endpoint on the server:

在此处输入图片说明

This is now working. Here is working code in case it may be helpful to others.

REACT

import React, {useEffect, useRef, useState, Component} from 'react';
import 'typeface-roboto';
import {makeStyles} from '@material-ui/styles';
import {useContext} from "../../context";
import Container from "@material-ui/core/Container";
import {DropzoneArea} from 'material-ui-dropzone'
import Button from "@material-ui/core/Button";

//ENDPOINTS
const receiveSpreadsheetEndpoint = '/spreadsheet_generator/api/receive-spreadsheet/';

function UploadSpreadsheet(props) {
  const classes = useStyles();
  const [{token}] = useContext();

  function handleImageUpload(event, theFile) {
    event.stopPropagation();
    event.preventDefault();

    let formData = new FormData()
    formData.append('file', theFile)
    fetch(receiveSpreadsheetEndpoint, {
      method: 'POST',
      body: formData,
      headers: {
        Authorization: `Bearer ${token}`,
      },
    })
      .then(response => response.json())
      .then(data => {
        console.log(data)
      })
      .catch(error => {
        console.error(error)
      })
  }

  function Dropzone(props) {
    const [file, setFile] = useState(null);

    function handleChange(event) {
      setFile(event[0]);
    }

    return (
      <>
        <DropzoneArea
          onChange={event => handleChange(event)}
          filesLimit={1}
        />

        <Button
          variant="contained"
          color="primary"
          onClick={event => handleImageUpload(event, file)}
        >
          Primary
        </Button>

      </>
    )
  }

  return (
    <Container className={classes.root} height="100%">
      <Dropzone
        acceptedFiles={['.csv', 'text/*', 'text/csv']}
        showPreviews={true}
        showFileNamesInPreview={true}
      />
    </Container>
  );
}

//https://material-ui.com/components/buttons/
const useStyles = makeStyles(theme => ({
    root: {
      '& > *': {
        margin: theme.spacing(1),
      },
    },
  }))
;

export default UploadSpreadsheet;

DJANGO REST ENDPOINT

from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.parsers import FormParser, MultiPartParser, JSONParser, FileUploadParser
import logging

from server_modules.spreadsheet.models import SourceSpreadsheet

logger = logging.getLogger(__name__)

logging.basicConfig(
    level=logging.DEBUG,
    format='%(name)s %(levelname)s %(message)s',
)

def create_spreadsheet_record(file):
    # insert record to SourceSpreadsheet
    SourceSpreadsheet.objects.create(file=file)

class ReceiveData(APIView):
    permission_classes = (IsAuthenticated,)
    parser_classes = (FileUploadParser,)

    def post(self, request):
        success = True
        message = 'OK'
        file = request.stream.FILES['file']

        # save to db
        try:
            create__spreadsheet_record(file)
        except Exception as e:
            print("Error calling ReceiveData: " + str(e))
            message = str(e)
            success = False

        data = {'message': message }
        if (success):
            return Response(data, status=status.HTTP_200_OK)
        else:
            return Response(data, status=status.HTTP_400_BAD_REQUEST)

DJANGO MODEL

class SourceSpreadsheet(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    file = models.FileField(upload_to='source_spreadsheets/%Y/%m')

BASE.PY Add:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM