简体   繁体   English

react + spring boot 上传文件和表单数据

[英]react + spring boot upload file and form data

i have a case like in my form (front end), i can fill personal data (name, address, DOB) and then i can attach multiple image.我的表格中有一个案例(前端),我可以填写个人数据(姓名、地址、出生日期),然后我可以附加多个图像。

In my spring boot controller:在我的 spring 启动 controller 中:

@RequestMapping(value = "/addCustOrder", method = RequestMethod.POST, consumes = {"multipart/form-data"})
    public String CustomerOrder(@ModelAttribute CustOrderRequest coReq, HttpServletRequest request) {
    System.out.println("debug ************** ");
    System.out.println("ReceiverName :: " + coReq.getReceiverName());
    System.out.println("attachmentFile :: " + coReq.getFileAttachment().length);
}

My model wrapper:我的 model 包装:

public class CustOrderRequest {
    private String receiverName;
    private String receiverPhone;
    private String itemDescription;
    private MultipartFile[] fileAttachment;
}
//setter & getter 

Front end (React) Code:前端(反应)代码:

const payload = JSON.stringify({
    id: values.id,
    receiverName: values.receiverName,
    receiverPhone: values.receiverPhone,
    itemDescription: values.itemDescription,
    fileAttachment: values.fileAttachment
});

axios.post(urlApi, payload)
    .then(r => {
    // success request 
    });

With above example, i always encounter errors.在上面的例子中,我总是遇到错误。 like: java.io.IOException: Stream closed and zero attachment length / zero attachment size (have switch from array of MultipartFile or List of MultipartFile).像:java.io.IOException:Stream 关闭且附件长度为零/附件大小为零(从 MultipartFile 数组或 MultipartFile 列表切换)。 please throw some light for this case, as a lot of tutorial out there only for upload the attachment part, not including the form data that user has filled.请对此案例有所了解,因为很多教程仅用于上传附件部分,不包括用户填写的表单数据。 Thanks before.之前谢谢。

tutorial reference: SO MK教程参考: SO MK

Updated front end code:更新的前端代码:

let fd = new FormData();
fd.append("fileAttachment", values.fileAttachment);
fd.append("receiverName", values.receiverName);

axios.post(urlApi, fd)
    .then(r => {
    // success request 
    });

changed the front end code using formdata then got error in backend:使用 formdata 更改了前端代码,然后在后端出错:

2020-02-07T17:36:10.231+0700 WARN Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'custOrderRequest' on field 'fileAttachment': rejected value [[object FileList]]; codes [typeMismatch.custOrderRequest.fileAttachment,typeMismatch.fileAttachment,typeMismatch.[Lorg.springframework.web.multipart.MultipartFile;,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [custOrderRequest.fileAttachment,fileAttachment]; arguments []; default message [fileAttachment]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile[]' for property 'fileAttachment'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile' for property 'fileAttachment[0]': no matching editors or conversion strategy found]]

You cant JSON stringify files.你不能 JSON 字符串化文件。 As far as I know in order to upload files through http you must post the data as form data.据我所知,为了通过 http 上传文件,您必须将数据作为表单数据发布。 This link's answer shows how to post formdata in axios. 此链接的答案显示了如何在 axios 中发布表单数据。 Your java end is probably already configured for form data input.您的 java 端可能已经配置为表单数据输入。

Edited已编辑

First Exception Solution第一个异常解决方案

You are consuming multipart/form-data in your server-side, so you must send data as formData .您正在服务器端使用multipart/form-data ,因此您必须将数据作为formData发送。

Use const formData = new FormData(form);使用const formData = new FormData(form); instead of JSON.stringify而不是JSON.stringify


Second Exception Solution第二个异常解决方案

Your second exception is for the binding error, you're trying to bind String into Multipart , it is because of this line你的第二个例外是绑定错误,你试图将String绑定到Multipart ,这是因为这一行

fd.append("fileAttachment", values.fileAttachment);

1- You can set an onChange in the form for file, like onFileChangeHandler 1-您可以在文件的表单中设置onChange ,例如onFileChangeHandler

<input type="file" className="form-control" name="file" onChange={this.onFileChangeHandler}/>

2- Set uploaded file in formData and send it (like below code) 2- 在formData设置上传的文件并发送它(如下面的代码)

Body of onChange can be as follows onChange主体可以如下

onFileChangeHandler = (e) => {
        e.preventDefault();
        this.setState({
            selectedFile: e.target.files[0]
        });
        const formData = new FormData();
        formData.append('file', this.state.selectedFile);
        //Append the rest data then send
        axios({
           method: 'post',
           url: 'myurl',
           data: formData,
           headers: {'Content-Type': 'multipart/form-data' }
        })
        .then(function (response) {
           //handle success
           console.log(response);
        }, 
        function(error) { 
           // handle error 
        });

below link might be useful for your case:以下链接可能对您的情况有用:

File Upload with React Js (Axios) and Spring REST 使用 React Js (Axios) 和 Spring REST 上传文件

if you use html+js as the frontend.如果您使用 html+js 作为前端。 when the file is not required, following maybe help:当不需要文件时,以下可能有帮助:

var formData = new FormData(document.getElementById("yourFormId"));

I faced this problem because of wrong form implementation in react.我遇到这个问题是因为 react 中的表单实现错误。

I was trying to append all the images at a time.我试图一次附加所有图像。

formData.append("images", images)

After looping over the images it solved my problem循环图像后,它解决了我的问题

for (let i = 0 ; i < images.length ; i++) {
    formData.append("images", images[i]);
}

Ohh well.. I understand哦,好吧。。我明白了

在此处输入图像描述

Into each array, exist the File property that spring boot converter in Multipart在每个数组中,存在 Multipart 中 spring 引导转换器的 File 属性

Code from my js:我的js中的代码:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM