简体   繁体   中英

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:

@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:

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). 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

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:

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. As far as I know in order to upload files through http you must post the data as form data. This link's answer shows how to post formdata in axios. Your java end is probably already configured for form data input.

Edited

First Exception Solution

You are consuming multipart/form-data in your server-side, so you must send data as formData .

Use const formData = new FormData(form); instead of 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

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

1- You can set an onChange in the form for file, like onFileChangeHandler

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

2- Set uploaded file in formData and send it (like below code)

Body of onChange can be as follows

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

if you use html+js as the frontend. 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.

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

Code from my js:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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