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

查看:20
本文介绍了无法将多部分表单数据从 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 = new FormData()formData.append('files', selectedFiles)formData.append('用户名', 用户名,)const { res} = sendDocument(formData)//参考下面的 reactTest.js 模块}返回 (<div className='myClass'>选择账单</div><空投区接受={'.pdf'}onDrop={selectedFiles =>handleUserFileUpload (selectedFiles)}>{({ getRootProps, getInputProps }) =>(<div {...getRootProps()} id='no-padding'><输入{...getInputProps()}类型='文件'id='附件'名称='附件'班级名称='我的班级'/>

)}</Dropzone>)}导出默认 UploadMyFiles

reactTest.js

export const sendDocument = async (myFormData) =>{返回等待 axios({方法:'发布',网址:`/sendDocument`,数据:myFormData,标头:{'内容类型':'多部分/表单数据'}});};

expressTest.Js 模块 [Node JS]

const express = require('express')const axios = require('axios')const 路由器 = express.Router()router.post('/', (req, res) => {console.log(req.body)//见下面的**输出,文件数据是字符串格式,这导致我的 axios 路由器调用后端的格式错误.我如何获得实际文件而不是这个 [目标文件].我相信这是因为multer bodyparserconsole.log(JSON.parse(req.body.myFormData.userName))轴({方法:'发布',url: '/sendMyUserData',数据:req.body,标题:{apiKey: 'keytoapi'//'Content-Type': 'multipart/form-data'}}).then(响应 => {返回 res.send(res)}).catch(错误=> {console.error('错误')}

**console.log 的输出

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

如您所见,文件"数据采用字符串格式,这导致我的 Axios 路由器调用后端的数据"格式错误.如何获取实际文件而不是这个 [目标文件]?我相信这是因为multer bodyparser.

我的后端 Java 端点

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

异常:

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

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

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

完整的请求标头 - 从浏览器网络选项卡的请求中捕获

请求地址:http://localhost:8080/sendMyUserData推荐人政策:strict-origin-when-cross-origin接受:应用程序/json、文本/纯文本、*/*接受编码:gzip、deflate、br接受语言:en-US,en;q=0.9,te;q=0.8授权:mytoken连接:保持连接内容长度:83474内容类型:多部分/表单数据;边界=----WebKitFormBoundaryvooZbILex2ARkOrsCookie:主机:本地主机:8080来源:http://localhost:8080引用者:http://localhost:8080/sendDocumentSec-Fetch-Dest:空Sec-Fetch-Mode:corsSec-Fetch-Site:同源用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(KHTML,如 Gecko)Chrome/88.0.4324.114 Safari/537.36------WebKitFormBoundaryvooZbILex2ARkOrs内容配置:表单数据;名称=用户名"测试用户------WebKitFormBoundaryvooZbILex2ARkOrs内容配置:表单数据;名称=文件";文件名=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天全站免登陆