Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
211 views
in Technique[技术] by (71.8m points)

javascript - Unable to send the multi part form data from React to Express Js correctly

I am trying to upload files using Dropzone and send these files to java back end API from React JS. Here React is sending the document to express back end and adding some keys and then sending the final form data to back end java endpoint. But not able to get the files and request part in the back end side. The express is getting the wrong format of the data Appreciate any help.

UploadMyFiles.jsx

const UploadMyFiles = () => {

  const [selectedFiles, setSelectedFiles]= useState(null)
  const [userName,setUserName]=userState('TestUser')

  const handleUserFileUpload = (userSelectedFiles) => {
        setSelectedFiles(userSelectedFiles)  

    const formData = new FormData()

    formData.append('files', selectedFiles)
    formData.append('userName', userName,)
    const { res} = sendDocument(formData) //refer reactTest.js module below

  }

  return (

          <div className='myClass'>Select Bill</div>
          <Dropzone
            accept={'.pdf'}
            onDrop={selectedFiles => handleUserFileUpload (selectedFiles)}
          >
            {({ getRootProps, getInputProps }) => (<div {...getRootProps()} id='no-padding'>
              <input
                {...getInputProps()}
                type='file'
                id='attachments'
                name='attachments'
                className='myclass'
              />              
            
            </div>
            )}
          </Dropzone>
  )
}
export default UploadMyFiles

reactTest.js

export const sendDocument = async (myFormData) => {
  return await axios({
    method: 'post',
    url: `/sendDocument`,
    data: myFormData,
    headers: { 'Content-Type': 'multipart/form-data' }
  });
};

expressTest.Js module [Node JS]

const express = require('express')
const axios = require('axios')
const router = express.Router()

router.post('/', (req, res) => {
  console.log(req.body) //see **output below, File data is in string format which is causing the wrong format in my axios router call to backend. How do I get actual file instead of this [object File]. I beliver it is because of multer bodyparser
  console.log(JSON.parse(req.body.myFormData.userName))
  axios({
    method: 'post',
    url: '/sendMyUserData',
    data: req.body,
    headers: {
      apiKey: 'keytoapi'
      //'Content-Type': 'multipart/form-data'
    }
  })
    .then(response => {
      
      return res.send(res)
    })
    .catch(error => {
      console.error('error')
     }

**output of the console.log

{"files":"[object File]","userName":"TestUser"}

As you see "files" data is in string format which is causing the wrong formData format for 'data' in my Axios router call to backend. How do I get the actual file instead of this [object File]? I believe it is because of multer bodyparser.

My backend Java endpoint

@PostMapping(path = "/sendMyUserData", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
        public String uploadMyUserData(@RequestPart(value = "files") final MultipartFile[] multipartFiles, @RequestPart(value = "userName", required = true) String userName ) {
            return myService.storeFiles(multipartFiles, userName));
    }

Exception:

org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=utf-8' not supported

I tried to set the content type in the expressTest.js module but I am getting all null values in the backend endpoint

'Content-Type': 'multipart/form-data;

enter image description here

full request headers -captured from my request from the browser network tab

Request URL: http://localhost:8080/sendMyUserData
Referrer Policy: strict-origin-when-cross-origin
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,te;q=0.8
Authorization:mytoken
Connection: keep-alive
Content-Length: 83474
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvooZbILex2ARkOrs
Cookie: Host: localhost:8080
Origin: http://localhost:8080
Referer: http://localhost:8080/sendDocument
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.114 Safari/537.36
------WebKitFormBoundaryvooZbILex2ARkOrs
Content-Disposition: form-data; name="userName"

TestUser
------WebKitFormBoundaryvooZbILex2ARkOrs
Content-Disposition: form-data; name="files"; filename="Xyz.pdf"
Content-Type: application/pdf
question from:https://stackoverflow.com/questions/65941537/unable-to-send-the-multi-part-form-data-from-react-to-express-js-correctly

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is that the append method of FormData takes either a string or a single file for the value, and "if none of these are specified the value is converted to a string". You are however passing an array of files (selectedFiles), which gets stringified to "[object File]" (if selecting two files at once, it would be [object File],[object File] - just what Array.prototype.toString and Object.prototype.toString do).

You will need to do

const UploadMyFiles = () => {
  const [userName,setUserName] = userState('TestUser')
  const handleUserFileUpload = (selectedFiles) => {
    const formData = new FormData()
    for (const file of selectedFiles)
      formData.append('files', file)
    formData.append('userName', userName)
    sendDocument(formData).catch(…)
  }

  return (
    <div className='myClass'>Select Bill</div>
      <Dropzone
        accept={'.pdf'}
        onDrop={handleUserFileUpload}
      >…</Dropzone>
    </div>
  )
}

Browser network tab enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...