使用 axios POST 请求将 JSON 数据作为 multipart/form-data 发送

Posted

技术标签:

【中文标题】使用 axios POST 请求将 JSON 数据作为 multipart/form-data 发送【英文标题】:Send JSON data as multipart/form-data using axios POST Request 【发布时间】:2021-07-02 10:12:16 【问题描述】:

以下 API 使用邮递员工作:

Spring boot,后端代码:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@Slf4j
public class UploadFile 
    @Autowired
    private FTPClient con;

    @PostMapping("/api/auth/uploadfiles")
    public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) 

        try 
            boolean result = con.storeFile(file.getOriginalFilename(), file.getInputStream());

            redirectAttributes.addFlashAttribute("message",
                    "You successfully uploaded " + file.getOriginalFilename() + "!");
         catch (Exception e) 
            log.error(e.getMessage(), e);
            redirectAttributes.addFlashAttribute("message",
                    "Could not upload " + file.getOriginalFilename() + "!");
        
        return "redirect:/";
    

ReactJS,前端代码:我在this.state.ipData 中有一组对象。

  exportFTP = async () => 
    
      const fromdata = this.state.ipData;
      alert("Data Send to FTP server");

    axios(
      method: 'post',
      url: 'http://localhost:8080/api/auth/uploadfiles',
      data: fromdata,
      header: 
        'Accept': 'application/json ,text/plain, */*',
        'Content-Type': 'multipart/form-data',
        //'Authorization': 'Bearer '+JWTToken,
      ,
    )
  

按钮触发功能:

<button
  style= marginRight: "2%", marginTop: "0.25%" 
  type="button"
  className="btn btn-info"
  onClick=() => this.exportFTP()
>
  Export to FTP
</button>

我需要将我的 frontend (ReactJS) 代码更改为使用邮递员进行 POST 请求时的代码。当前 JS 代码导致以下错误响应:

Servlet.service() 用于路径 [] 上下文中的 servlet [dispatcherServlet] 引发异常 [请求处理失败;嵌套异常是 org.springframework.web.multipart.MultipartException: Current request is not a multipart request] 有根本原因

请注意,API 在使用 Postman 时有效。 如何修复 JS 代码?

【问题讨论】:

我尝试使用表单数据,但我完全不知道如何处理我所在州的数据。 它保存了组件的当前状态,一些数组数据 是的,我想我需要该数组来转换 JSON 文件或其他东西,但我找不到任何有用的资源。 (5557) [..., ..., ..., ..., ..., ..., ..., ..., ..., ... 、…、…、…、…、…、…、…、…、…、…、…、…、 …、…、…、…、…、…、…、…、…、…、…、…、… 、…、…、…、…、…、…、…、…、…、…、…、…、 …、…、…、…、…、…、…、…、…、…、…、…、… 、…、…、…、…、…、…、…、…、…、…、…、…、 …、…、…、…、…、…、…、…、…、…、…、…、… 、…、…、…、…、…、…、…、…、…、…、…、…、 …、…、…、…] 【参考方案1】:

您在多部分请求中将 JSON 数据作为 Blob 发送。所以,你需要使用Blob API。

创建一个从 JSON 数据创建 blob 的函数:

function jsonBlob(obj) 
  return new Blob([JSON.stringify(obj)], 
    type: "application/json",
  );

并在请求中使用这个函数:

exportFTP = async () => 
  const formData = new FormData();
  formData.append("file", jsonBlob(this.state.ipData))

  axios(
    method: "post",
    url: "http://localhost:8080/api/auth/uploadfiles",
    data: formData,

    /* You had a Typo: it is "headers" not "header".
    And, multipart/form-data header should get set automatically 
    as we used FormData. You might not need to add that manually. */
    // You may also not need Accept header; (should be set automatically).
    
    headers:  
      Accept: "application/json ,text/plain, */*",
      "Content-Type": "multipart/form-data",
      // 'Authorization': 'Bearer '+ JWTToken,
    ,
  );
;

【讨论】:

这确实有效,有什么方法可以减小 jsonBlob 的大小 Servlet.service() for servlet [dispatcherServlet] 在路径 [] 的上下文中抛出异常 [请求处理失败;嵌套异常是 org.springframework.web.multipart.MaxUploadSizeExceededException: 超过最大上传大小;嵌套异常是 java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: 字段文件超出其最大允许大小 1048576 字节。] 根本原因 我使用了在我的本地 macine 上运行的 apache FTP 服务器。但是我的代码没有任何限制。 非常感谢你,我只是将 spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB 添加到 application.properties 并且它现在可以工作了 是的,你是对的:Max limit of MultipartFile in Spring Boot【参考方案2】:

尝试移除头部并发送请求

    exportFTP = async () => 
    
      const fromdata = this.state.ipData;
      alert("Data Send to FTP server");

    axios(
      method: 'post',
      url: 'http://localhost:8080/api/auth/uploadfiles',
      data: fromdata
    ).then(function (res) 
      if (res.ok) 
        alert("Perfect! ");
       else if (res.status == 401) 
        alert("Oops! ");
      
    , function (e) 
      alert("Error submitting form!");
    );

【讨论】:

感谢您关注我的问题。但是,我仍然从后端得到同样的错误。

以上是关于使用 axios POST 请求将 JSON 数据作为 multipart/form-data 发送的主要内容,如果未能解决你的问题,请参考以下文章

使用 axios POST 请求将 JSON 数据作为 multipart/form-data 发送

使用axios请求数据,post请求出错。因为axios传递的请求参数是json格式,而后端接口要求是formData

Vue使用axios请求数据,默认post请求传参是json格式,但后台需要formData格式???

axios发送post请求,如何提交表单数据?

发生错误 400(错误请求)时,使用 Axios 从 POST 捕获返回 json

vue中的axios.post使用json数据传输,出现请求头字段内容类型是不被允许的情况的解决方案