无法将多部分表单数据从 React 正确发送到 Express Js
Posted
技术标签:
【中文标题】无法将多部分表单数据从 React 正确发送到 Express Js【英文标题】:Unable to send the multi part form data from React to Express Js correctly 【发布时间】:2021-05-02 14:37:27 【问题描述】:我正在尝试使用 Dropzone 上传文件并将这些文件从 React JS 发送到 java 后端 API。这里 React 将文档发送到 express 后端并添加一些键,然后将最终的表单数据发送到后端 java 端点。但无法在后端获取文件和请求部分。快递收到的数据格式错误,感谢任何帮助。
上传我的文件.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 模块 [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')
**console.log 的输出
"files":"[object File]","userName":"TestUser"
如您所见,“文件”数据是字符串格式,这导致我的 Axios 路由器调用后端时“数据”的 formData 格式错误。如何获取实际文件而不是此 [目标文件]?我相信这是因为 multer bodyparser。
我的后端 Java 端点
@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));
例外:
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=utf-8' not supported
我尝试在 expressTest.js 模块中设置内容类型,但我在后端端点中获得了所有空值
'Content-Type': 'multipart/form-data;
完整的请求标头 - 从浏览器网络选项卡的请求中捕获
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
【问题讨论】:
java 后端无关。您的 express.js 代理服务器已经收到错误的请求数据 -res.body
甚至似乎是一个 JSON 文档。请edit您的问题包括与从输入元素获取文件并使用 axios 发出请求相关的完整前端代码。
感谢@Bergi 查看它。我已经更新了帖子并包含了具有发送 formData 逻辑的代码
您使用的是哪个Dropzone
库,that one?
@Bergi,这是正确的 react-dropzone
顺便说一句,setSelectedFiles(userSelectedFiles)
钩子使用错误,附加 selectedFiles
将附加旧值。
【参考方案1】:
问题在于the append
method of FormData
使用字符串或单个文件作为值,并且“如果没有指定这些值,则值将转换为字符串”。但是,您正在传递一个 array 文件 (selectedFiles
),它被字符串化为 "[object File]"
(如果一次选择两个文件,它将是 [object File],[object File]
- 正是 Array.prototype.toString
和 @ 987654331@做)。
你需要这样做
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>
)
浏览器网络选项卡
【讨论】:
我几个小时前刚做过。我尝试使用 formData.append("files[], selectedFiles[0]) 并尝试现在只发送一个文件。我仍然可以看到输出为 [Object: null prototype] folderName: 'TestUser' adding files[] ,向我显示网络 heders 选项卡中的文件名,文件作为二进制文件(二进制)发送,但不显示其他任何内容,我的后端无法读取,说多部分异常和读取超时 @mark 现在这意味着您的前端终于可以正常工作了,可以正确发送文件,而您的后端需要修复。请接受这个关于前端部分的答案,然后用新信息更新the question about the backend,我们可以在那里讨论如何正确使用 multer。 我不确定它是否正常工作,但 console.log(req.body.files) 仍然显示 [object null prototype] userName:'TestUser' 在浏览器网络选项卡中是单个文件的文件(二进制)。感谢您的检查,但一旦它工作,我肯定会接受。当我从邮递员测试时,后端已经在工作,我认为后端没有任何问题 添加了我的网络标签的屏幕截图。这是预期的,还是在快递方面遗漏了什么?以上是关于无法将多部分表单数据从 React 正确发送到 Express Js的主要内容,如果未能解决你的问题,请参考以下文章
CORS XMLHttpRequest 使用 POST 将多部分表单数据发送到 Softlayer 对象存储失败