Вызов службы REST Spring Boot 2 с multipart / form-data с Postman приводит к EOFException - PullRequest
0 голосов
/ 11 октября 2019

Работая над личным проектом в Spring Boot, я должен разработать веб-сервис, который принимает файл и некоторые метаданные, и я решил протестировать его с клиентом Postman.

Версии, которые я использую:

  • Версия Почтальон: Почтальон для Mac Версия 7.8.0 OS X 18.7.0 / x64
  • Версия Java: 1.8.0_212
  • Версия для весенней загрузки: 2.1. 1.RELEASE

Поскольку метаданные потенциально могут быть достаточно структурированными, я решил использовать тип содержимого multipart / form-data, состоящий из двух частей:

  • a "file "часть, содержащая файл
  • часть" body ", содержащая json с метаданными

Я настроил вызов в Postman следующим образом postman screenshot

Теперь весенняя загрузка конфигурации. Прежде всего, я добавил следующие строки в application.properties:

## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=20MB
# Max Request Size
spring.servlet.multipart.max-request-size=25MB

Затем я создал свой контроллер с конечной точкой

@PostMapping(Paths.Registrations.BASE)
@ResponseBody
public PostRegistrationResponseDto postRegistration(@RequestParam("file") MultipartFile file, @RequestParam("body") PostRegistrationRequestDto req) {
    PostRegistrationResponseDto resp = new PostRegistrationResponseDto();
    resp.setId(new Random().nextLong());
    resp.setFileName(req.getFileName());
    resp.setRegistrationTime(LocalDateTime.now());

    return resp;
}

К сожалению, вызов недаже прибываю в Spring: я получаю ошибку HTTP 500 с этим телом

<!doctype html>
<html lang="en">

<head>
    <title>HTTP Status 500 – Internal Server Error</title>
    <style type="text/css">
        ...
    </style>
</head>

<body>
    <h1>HTTP Status 500 – Internal Server Error</h1>
</body>

</html>

В моем журнале сервера я не получаю исключений, но когда я установил отладчик для блокировки исключений, я увидел, что tomcat запускает исключение EOFс этой трассировкой стека

java.io.EOFException
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1208)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1142)
at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:729)
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:352)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:294)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

Признаюсь, я даже не знаю, с чего начать ... Может кто-нибудь подсказать мне, что я делаю неправильно?

Спасибо :)

1 Ответ

0 голосов
/ 14 октября 2019

В конце концов я обнаружил, что Tomcat генерирует множество исключений, не всегда значимых.

Проблема, с которой я столкнулся, была связана не с этим исключением, а с тем, что Spring не работает автоматическисопоставить строковую часть с Dto.

Чтобы все работало, мне нужно было написать этот компонент:

package it.aegidea.proofy.api.converters;

import com.fasterxml.jackson.databind.ObjectMapper;
import it.aegidea.proofy.api.dtos.proofyapi.PostRegistrationRequestDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class PostRegistrationRequestDtoConverter implements Converter<String, PostRegistrationRequestDto> {

    private final ObjectMapper objectMapper;

    @Autowired
    public PostRegistrationRequestDtoConverter(final ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public PostRegistrationRequestDto convert(String source) {
        try {
            return objectMapper.readValue(source, PostRegistrationRequestDto.class);
        } catch (IOException e) {
            return null;
        }
    }

}

Таким образом Spring понял, как сопоставить строку с PostRegistrationRequestDto и могуспешно сопоставить запрос с типами на конечной точке.

...