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

Posted

技术标签:

【中文标题】react + spring boot 上传文件和表单数据【英文标题】:react + spring boot upload file and form data 【发布时间】:2020-05-23 10:51:45 【问题描述】:

我的表格中有一个案例(前端),我可以填写个人数据(姓名、地址、出生日期),然后我可以附加多个图像。

在我的 Spring Boot 控制器中:

@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);

我的模型包装器:

public class CustOrderRequest 
    private String receiverName;
    private String receiverPhone;
    private String itemDescription;
    private MultipartFile[] fileAttachment;

//setter & getter 

前端(React)代码:

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

在上面的例子中,我总是遇到错误。像:java.io.IOException:流已关闭且附件长度为零/附件大小为零(已从 MultipartFile 数组或 MultipartFile 列表切换)。 请对此案例有所了解,因为很多教程仅用于上传附件部分,不包括用户填写的表单数据。之前谢谢。

教程参考:SOMK

更新前端代码:

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

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

使用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]]

【问题讨论】:

文件很大吗?文件以什么格式发送?您能否在 .then() 之后添加 .catch((err) => console.log(err.message) ) 并告诉它何时显示或显示该帖子的浏览器调试器网络结果?您是否尝试过将文件作为二进制(字符串)发送,然后在后端编译? JSON.stringify 文件看起来很奇怪。 对不起,是的,它不适合 JSON.stringify 附件。我已更改代码以使用 formdata。它抛出另一个错误。 【参考方案1】:

已编辑

第一个异常解决方案

您在服务器端使用multipart/form-data,因此您必须以formData 发送数据。

使用const formData = new FormData(form);代替JSON.stringify


第二个异常解决方案

您的第二个例外是绑定错误,您尝试将String 绑定到Multipart,这是因为这一行

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

1- 您可以在文件的表单中设置onChange,例如onFileChangeHandler

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

2- 在formData 中设置上传文件并发送(如下代码)

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

以下链接可能对您的情况有用:

File Upload with React Js (Axios) and Spring REST

【讨论】:

我已经更新了我的前端代码,现在它导致后端出现类型不匹配错误。我应该如何从前端发送附件格式? 这是绑定错误,您正在尝试将字符串绑定到多部分,请检查上传文件(检查表格中的类型,必须是文件)。就像您发送字符串而不是服务器文件一样 @cumibulat 能否请您向我们展示您的查看代码? @cumibulat 你的问题在fd.append("fileAttachment", values.fileAttachment); 我已经浏览了您分享的链接,我可以从该教程中即兴创作。谢谢。之前看过该链接,但没有完全注意 multipartfile + extras 参数。【参考方案2】:

您不能对文件进行 JSON 字符串化。据我所知,为了通过 http 上传文件,您必须将数据作为表单数据发布。 This link's 答案展示了如何在 axios 中发布 formdata。您的 java 端可能已经配置为表单数据输入。

【讨论】:

我已经更新了我的前端代码,现在它导致后端出现类型不匹配错误。我应该如何从前端发送附件格式?【参考方案3】:

如果你使用 html+js 作为前端。当不需要该文件时,以下可能会有所帮助:

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

【讨论】:

我注意到您发布了一个非常相似的答案here。请避免对多个问题发布相同的答案。【参考方案4】:

由于 react 中的表单实现错误,我遇到了这个问题。

我试图一次附加所有图像。

formData.append("images", images)

遍历图像后,它解决了我的问题

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

【讨论】:

以上是关于react + spring boot 上传文件和表单数据的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 控制器 - 将 Multipart 和 JSON 上传到 DTO

Spring Boot 与 Kotlin 上传文件

峰哥说技术:12-Spring Boot文件上传

Spring Boot 中的文件上传:上传、验证和异常处理

Spring Boot 上传文件

Spring Boot 文件操作,上传浏览和删除