Загрузка файла Spring WebFlux: неподдерживаемый тип носителя 415 с многочастной загрузкой - PullRequest
0 голосов
/ 21 мая 2019

Я сталкиваюсь с некоторыми проблемами при обработке загрузки файлов с использованием реактивной среды Spring. Я думаю, что я следую за документами, но не могу уйти от этой 415 / Unsupported Media Type проблемы.

Мой контроллер выглядит как показано ниже (согласно примеру здесь: https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-multipart-forms)

package com.test.controllers;

import reactor.core.publisher.Flux;

import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<String> uploadHandler(@RequestBody Flux<Part> parts) {
        return parts
                .filter(part -> part instanceof FilePart)
                .ofType(FilePart.class)
                .log()
                .flatMap(p -> Flux.just(p.filename()));
    }

}

POSTING к этой конечной точке, всегда дает мне один и тот же вывод:

curl -X POST -F "data=@basic.ppt" http://localhost:8080/upload
---
"Unsupported Media Type","message":"Content type 'multipart/form-data;boundary=------------------------537139718d79303c;charset=UTF-8' not supported"

Я тоже пытался использовать @RequestPart("data"), но получаю похожую ошибку Unsupported Media Type, хотя и с типом содержимого файла.

Похоже, у Spring возникают проблемы с преобразованием их в Part ..? Я застрял - любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 29 мая 2019

Спасибо @kojot за ваш ответ, но в этом случае я обнаружил, что проблема заключалась в моем кратковременном включении spring-webmvc в дополнение к spring-webflux.Ваше решение, вероятно, тоже сработало бы, но я хотел придерживаться стиля Контроллера, поэтому в итоге принудительно исключил spring-webmvc из моего build.gradle:

configurations {
    implementation {
        exclude group: 'org.springframework', module: 'spring-webmvc'
    }
}

После этого оно работало, как описано.

0 голосов
/ 22 мая 2019

Ну, это не прямой ответ на ваш вопрос, потому что я использую функциональные конечные точки, но я надеюсь, что это поможет вам как-то.

import org.springframework.context.annotation.Bean;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.stereotype.Controller;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import java.io.File;
import java.util.Map;

import static org.springframework.web.reactive.function.BodyInserters.fromObject;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Controller
public class FileUploadController {

    @Bean
    RouterFunction<ServerResponse> apiRoutes() {
        return nest(path("/api"),
                route(POST("/upload"), fileUpload()));
    }

    private HandlerFunction<ServerResponse> fileUpload() {
        return request -> {
            return request.body(BodyExtractors.toMultipartData()).flatMap(parts -> {
                        Map<String, Part> map = parts.toSingleValueMap();
                        final FilePart filePart = (FilePart) map.get("file");
                        final String dir = "C:\\JDeveloper\\mywork\\Spring\\SpringTest\\webflux-file-upload\\uploaded";
                        filePart.transferTo(new File(dir + "/" + filePart.filename()));

                        return ServerResponse.ok().body(fromObject("ok, file uploaded"));
                    }
            );
        };
    }

}

Вы можете загрузить файл с curl следующим образом:

curl -F "file=@C:\Users\Wojtek\Desktop\img-5081775796112008742.jpg" localhost:8080/api/fileupload
...