如何将文件从 Quarkus 发送到 Spring Boot 应用程序?

问题描述 投票:0回答:2

我正在编写一个 Quarkus 微服务,旨在与主 Spring Boot 应用程序进行通信。

为了调用 Spring Boot 应用程序,我基于此 Quarkus 教程 编写了一个 REST 客户端,并且它在某些端点上运行良好。 当我尝试将文件从 Quarkus 上传到 Spring boot 时,问题发生了,我无法让它正常工作。我按照这个其他教程来处理多部分请求。

这是我的 Quarkus 应用程序上的多部分对象:

public class MultipartBody {
    @FormParam("file")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    public InputStream file;

    @FormParam("fileName")
    @PartType(MediaType.TEXT_PLAIN)
    public String fileName;
}

这是 Quarkus 中 REST 客户端的端点:

@POST
@Path("/file")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
ProjectFile upload(@HeaderParam(AUTH_HEADER) String apiToken, @MultipartForm MultipartBody data);

以下是我构建 MultipartBody 对象的方法:

    InputStream stream = IOUtils.toInputStream(contentString, Charset.defaultCharset());
    MultipartBody data = MultipartBody.builder()
            .file(stream)
            .fileName(filename)
            .build();

Spring Boot应用程序中的端点:

@PostMapping("/file")
public ProjectFile receive(@RequestParam MultipartFile inputFile)

它抛出一个错误,指出未提供

inputFile

Required request part 'inputFile' is not present - org.springframework.web.multipart.support.MissingServletRequestPartException - Required request part 'inputFile' is not present

如果我将

@RequestParam
更改为
@RequestBody
,则
inputFile
参数始终为
null
。我错过了什么?

java spring-boot resteasy quarkus quarkus-rest-client
2个回答
1
投票

尝试使用

MultipartFormDataOutput
类,多部分表单数据字段缺少文件名。在您的情况下,尝试使用
@PartFilename
注释。

必须与@MultipartForm结合使用。这定义了零件的文件名

try (InputStream fileInputStream = new FileInputStream(currentFile)) {

  MultipartFormDataOutput multipartFormDataOutput = new MultipartFormDataOutput();

  multipartFormDataOutput.addFormData("file", fileInputStream, MediaType.APPLICATION_OCTET_STREAM_TYPE, currentFile.getName());
  
  multipartFormDataOutput.addFormData("metaData",objectMapper.writeValueAsString(fileMeta),MediaType.APPLICATION_JSON_TYPE);

  // Call client to upload file

} 

0
投票

随着 Quarkus 转向休息客户端响应式,正确的用法将是使用该类

QuarkusMultipartForm

让我们采用下面的示例,但具有多个文件和一个字符串负载,这也是 Spring 控制器端点所期望的。

@PostMapping(path = "/multipart",
      consumes = MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
  public Map<String, String> multipart(@RequestParam String jsonPayload,
      @RequestPart MultipartFile[] files) {
    return Map.of("fileName", String.join(": ", "File received is : ", files[0].getName()));
  }

调用端点的 Quarkus 应用程序将如下所示 基于轻松反应,我们可以通过自定义调用或 MultipartFormDataInput 接收数据。

public class MultiPartPayloadFormData {

  @RestForm("files")
  @PartType(MediaType.APPLICATION_OCTET_STREAM)
  List<FileUpload> files;

  @RestForm("jsonPayload")
  @PartType(MediaType.TEXT_PLAIN)
  String jsonPayload;
}

对 Spring 端点的服务调用是通过

@RegisterRestClient(configKey = "spring-multipart")
@RegisterClientHeaders
@Path("/api")
public interface MultipartSpringService {

  @POST
  @Path("/multipart")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces(MediaType.APPLICATION_JSON)
  Map<String, String> springMultipartCall(QuarkusMultipartForm dataParts);

  @POST
  @Path("/test")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces(MediaType.APPLICATION_JSON)
  Map<String, String> testCallSpring(@RestForm("payload") String payload);
}

现在我们需要构建

QuarkusMultipartForm
对象。

  @POST
  @Path("/multipart")
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  public Map<String, String> multipart(MultiPartPayloadFormData data) {

    QuarkusMultipartForm qmf = new QuarkusMultipartForm();
    qmf.attribute("jsonPayload", data.getJsonPayload(), "jsonPayload");
    data.getFiles().forEach(f -> {
      qmf.binaryFileUpload("file", f.name(), f.filePath().toString(), f.contentType());
    });

    return springService.springMultipartCall(qmf);
  }

对于实际问题的具体答案

@PostMapping("/file")
public ProjectFile receive(@RequestParam MultipartFile inputFile)

解决方案将是

@RegisterRestClient(configKey = "spring-multipart")
@RegisterClientHeaders
public interface MultipartSpringService {

  @POST
  @Path("/file")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  @Produces(MediaType.APPLICATION_JSON)
  Map<String, String> springReceiveCall(QuarkusMultipartForm dataParts);

该方法的调用将如下所示

    QuarkusMultipartForm qmf = new QuarkusMultipartForm();
    qmf.binaryFileUpload("inputFile", f.name(), f.filePath().toString(), f.contentType());
    });
    return springService.springReceiveCall(qmf);

© www.soinside.com 2019 - 2024. All rights reserved.