问题
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;
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
回答1:
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
来源:https://stackoverflow.com/questions/65941537/unable-to-send-the-multi-part-form-data-from-react-to-express-js-correctly