【问题标题】:How do I send a multipartFile using spring RestTemplate?如何使用 spring RestTemplate 发送 multipartFile?
【发布时间】:2019-08-03 22:22:32
【问题描述】:

我正在尝试将文件从一个 SpringBoot 应用程序发布到另一个 SpringBoot 应用程序。 我试图到达的终点看起来像

@PostMapping(
        value = "/upload",
        consumes = MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<ArmResponse<JobData>> uploadInvoices(@RequestParam("file") MultipartFile interestingStuff) {

    String incomingFilename = interestingStuff.getName();
    String originalFilename = interestingStuff.getOriginalFilename();
    String contentType = interestingStuff.getContentType();

    // do interesting stuff here

    return ok(successfulResponse(new JobData()));
}

应用程序中对 thios 端点执行 POST 请求的代码如下所示

public void loadInvoices(MultipartFile invoices) throws IOException {

    File invoicesFile = new File(invoices.getOriginalFilename());
    invoices.transferTo(invoicesFile);

    LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
    parts.add("file", invoicesFile);


    HttpHeaders httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

    HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);

    String url = String.format("%s/rest/inbound/invoices/upload", baseUrl);

    final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    messageConverters.add(new ByteArrayHttpMessageConverter());
    messageConverters.add(new ResourceHttpMessageConverter());
    messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    messageConverters.add(new FormHttpMessageConverter());
    messageConverters.add(new SourceHttpMessageConverter<Source>());

    RestTemplate template = new RestTemplate(messageConverters);

    template.exchange(
            url,
            HttpMethod.POST,
            httpEntity,
            new ParameterizedTypeReference<ArmResponse<JobData>>() {

            });
}

如果我使用邮递员以表格形式发布文件 - 它可以工作 Postman 请求中的内容类型标头看起来像

content-type:"multipart/form-data; boundary=--------------------------286899320410555838190774"

当 RestTemplate 执行 POST 时,出现以下错误。

com.fasterxml.jackson.databind.exc.MismatchedInputException: 由于 [Source: (String)"" 的输入结束,没有要映射的内容;行:1,列:0]

我怀疑请求中发送的内容类型标头是错误的。 有谁知道如何正确设置 MULTIPART_FORM_DATA 的内容类型标头?

【问题讨论】:

    标签: spring spring-boot multipartform-data resttemplate


    【解决方案1】:

    为什么需要 messageConverters?只需简单地使用本教程中的代码:https://www.baeldung.com/spring-rest-template-multipart-upload

    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<String> response = restTemplate
      .postForEntity(url , httpEntity, String.class);
    

    【讨论】:

    • 感谢您的回复。我几乎从那个确切的教程开始。我希望它能够工作,但事实并非如此。我收到问题中提到的错误。我添加了 MessageConverters 作为我让它工作的许多尝试的一部分。现在删除它们并回到教程中的香草解决方案,我会看看它是否有效。
    • 不,我仍然得到; "com.fasterxml.jackson.databind.exc.MismatchedInputException: 由于输入结束 arm-ui_1 | 在 [Source: (String)"" 处没有要映射的内容;行:1,列:0]
    【解决方案2】:

    与往常一样,解决方案非常简单。只需在 multipartFile 上调用 getResource()。

    public void loadInvoices(MultipartFile invoices) throws IOException {
    
        Resource invoicesResource = invoices.getResource();
    
        LinkedMultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
        parts.add("file", invoicesResource);
    
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    
        HttpEntity<LinkedMultiValueMap<String, Object>> httpEntity = new HttpEntity<>(parts, httpHeaders);
    
        restTemplate.postForEntity("my/url", httpEntity, SommeClass.class);
    }
    

    【讨论】:

    • 我的问题已经被invices.getResource( )解决了,谢谢:D
    【解决方案3】:

    Kotlin 中一个更漂亮的解决方案:

        @Test
        fun testMultipartUpload() {
            val bytes = ByteArray(10240) // Get your bytes however you like.
            val resource = object : ByteArrayResource(bytes) {
                override fun getFilename() = "xyzzy.jpg"
            }
            val request = RequestEntity.post("/foobar")
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(LinkedMultiValueMap<String, Any>().apply { add("data", resource) })
            val result = testRestTemplate.exchange(request, FooBar::class.java)
            Assertions.assertTrue(result.statusCode.is2xxSuccessful)
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-18
      • 2020-07-23
      • 2016-05-29
      • 2017-11-14
      • 2017-07-01
      • 2023-03-09
      • 2020-05-10
      • 2019-06-18
      相关资源
      最近更新 更多