无法将多部分表单数据从React正确发送到Express Js [英] Unable to send the multi part form data from React to Express Js correctly

查看:65
本文介绍了无法将多部分表单数据从React正确发送到Express Js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Dropzone上传文件,并将这些文件从React JS发送到Java后端API.这里,React发送文档来表示后端并添加一些键,然后将最终的表单数据发送到后端Java端点.但是无法获取文件并在后端请求部分.快递收到的数据格式错误谢谢您的帮助.

UploadMyFiles.jsx

  const UploadMyFiles =()=>{const [selectedFiles,setSelectedFiles] = useState(null)const [userName,setUserName] = userState('TestUser')const handleUserFileUpload =(userSelectedFiles)=>{setSelectedFiles(userSelectedFiles)const formData =新的FormData()formData.append('files',selectedFiles)formData.append('userName',userName,)const {res} = sendDocument(formData)//参考下面的reactTest.js模块}返回 (< div className ='myClass'>选择Bill</div>< Dropzoneaccept = {'.pdf'}onDrop = {selectedFiles =>handleUserFileUpload(selectedFiles)}>{({getRootProps,getInputProps})=>(< div {... getRootProps()} id ='no-padding'><输入{... getInputProps()}类型='文件'id ='附件'名称=附件"className ='myclass'/></div>)}</Dropzone>)}导出默认的UploadMyFiles 

reactTest.js

  export const sendDocument =异步(myFormData)=>{返回等待axios({方法:发布",网址:`/sendDocument`,数据:myFormData,标头:{'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)//请参见下面的**输出,文件数据为字符串格式,这导致我的axios路由器调用后端的格式错误.如何获取实际文件而不是此[目标文件].我敢说这是因为multerparserconsole.log(JSON.parse(req.body.myFormData.userName))axios({方法:发布",网址:"/sendMyUserData",数据:req.body,标头:{apiKey:'keytoapi'//'Content-Type':'multipart/form-data'}}).then(response => {返回res.send(res)}).catch(错误=> {console.error('错误')} 

** console.log的输出

  {文件":"[目标文件]",用户名":"TestUser"} 

如您所见,文件"数据为字符串格式,这会导致Axios路由器对后端的调用中数据"的格式错误.如何获取实际文件而不是此[目标文件]?我相信这是因为有机身分析器.

我的后端Java端点

  @PostMapping(路径="/sendMyUserData",消耗= {MediaType.MULTIPART_FORM_DATA_VALUE})public String uploadMyUserData(@RequestPart(value ="files"))final MultipartFile [] multipartFiles,@RequestPart(value ="userName",required = true)字符串userName){返回myService.storeFiles(multipartFiles,userName));} 

例外:

  org.springframework.web.HttpMediaTypeNotSupportedException:内容类型'application/json; charset = utf-8'不支持 

我试图在expressTest.js模块中设置内容类型,但是我在后端端点中获取了所有空值

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

完整的请求标头-从我的浏览器网络"标签中的请求中捕获的

 请求URL:http://localhost:8080/sendMyUserData推荐人政策:严格原产地-跨原产地接受:application/json,text/plain,*/*接受编码:gzip,deflate,br接受语言:en-US,en; q = 0.9,te; q = 0.8授权:mytoken连接:保持活动状态内容长度:83474内容类型:多部分/表单数据;boundary = ---- WebKitFormBoundaryvooZbILex2ARkOrsCookie:主机:localhost:8080来源:http://localhost:8080引荐来源:http://localhost:8080/sendDocument秒提取目标:空安全提取模式:cors安全提取站点:同源用户代理:Mozilla/5.0(Windows NT 10.0; Win64; x64)AppleWebKit/537.36(KHTML,如Gecko)Chrome/88.0.4324.114 Safari/537.36------ WebKitFormBoundaryvooZbILex2ARkOrs内容处置:表单数据;name ="userName";测试用户------ WebKitFormBoundaryvooZbILex2ARkOrs内容处置:表单数据;名称=文件";filename ="Xyz.pdf"内容类型:应用程序/pdf 

解决方案

问题是

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

解决方案

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

这篇关于无法将多部分表单数据从React正确发送到Express Js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆