英文:
How to provide swagger annotation for MultipartFormDataInput in RestEasy with Quarkus
问题
在使用 Quarkus 和 RestEasy 框架工作时,我有一个使用 MultipartFormDataInput
上传文件的功能。这个功能按预期工作,但我无法为 Swagger UI 提供正确的 Open API 注解。我尝试了多个选项和组合,但没有成功。请帮助我。我提供以下示例代码。
@Operation(summary = "上传单个文件", description = "上传单个文件")
@APIResponses({
@APIResponse(responseCode = "200", description = "成功上传文件"),
@APIResponse(name = "500", responseCode = "500", description = "内部服务错误")
})
@RequestBody(content = @Content(
mediaType = MediaType.MULTIPART_FORM_DATA,
schema = @Schema(type = SchemaType.STRING, format = "binary"),
encoding = @Encoding(name = "attachment", contentType = "application/octet-stream")))
@POST
@Path("/singleFile")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public Response handleFileUpload(@MultipartForm MultipartFormDataInput input) {
String fileName = null;
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
// 获取要保存的文件数据
List<InputPart> inputParts = uploadForm.get("attachment");
for (InputPart inputPart : inputParts) {
try {
MultivaluedMap<String, String> header = inputPart.getHeaders();
fileName = getFileName(header);
InputStream inputStream = inputPart.getBody(InputStream.class, null);
byte[] bytes = IOUtils.toByteArray(inputStream);
File customDir = new File(UPLOAD_DIR);
if (!customDir.exists()) {
customDir.mkdir();
}
fileName = customDir.getCanonicalPath() + File.separator + fileName;
Files.write(Paths.get(fileName), bytes, StandardOpenOption.CREATE);
return Response.status(200).entity("已上传文件名 : " + fileName).build();
} catch (Exception e) {
e.printStackTrace();
}
}
return Response.status(200).entity("已上传文件名 : " + fileName).build();
}
我还参考了以下链接:
https://github.com/swagger-api/swagger-core/issues/3050
如果我创建一个名为 MultipartBody
的单独类,并使用 @Schema(type = SchemaType.STRING, format = "binary")
和 @PartType(MediaType.APPLICATION_OCTET_STREAM)
注解,我可以生成 Swagger UI。但我的要求是仅使用 MultipartFormDataInput
。
英文:
while working on Quarkus with the RestEasy framework, I have the functionality to upload a file using MultipartFormDataInput
. This functionality is working as expected, but I am unable to provide proper open API annotation for swagger UI. I have tried multiple options and combinations, but it did not bear fruit. Please help me. I provide below the sample code.
@Operation(summary = "Upload a single file", description = "Upload a single file")
@APIResponses({
@APIResponse(responseCode = "200", description = "Upload file successfully"),
@APIResponse(name = "500", responseCode = "500", description = "Internal service error") })
@RequestBody(content = @Content(
mediaType = MediaType.MULTIPART_FORM_DATA,
schema = @Schema(type = SchemaType.STRING, format = "binary"),
encoding = @Encoding(name = "attachment", contentType = "application/octet-stream")))
@POST
@Path("/singleFile")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public Response handleFileUpload(@MultipartForm MultipartFormDataInput input) {
String fileName = null;
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
// Get file data to save
List<InputPart> inputParts = uploadForm.get("attachment");
for (InputPart inputPart : inputParts) {
try {
MultivaluedMap<String, String> header = inputPart.getHeaders();
fileName = getFileName(header);
InputStream inputStream = inputPart.getBody(InputStream.class, null);
byte[] bytes = IOUtils.toByteArray(inputStream);
File customDir = new File(UPLOAD_DIR);
if (!customDir.exists()) {
customDir.mkdir();
}
fileName = customDir.getCanonicalPath() + File.separator + fileName;
Files.write(Paths.get(fileName), bytes, StandardOpenOption.CREATE);
return Response.status(200).entity("Uploaded file name : " + fileName).build();
} catch (Exception e) {
e.printStackTrace();
}
}
return Response.status(200).entity("Uploaded file name : " + fileName).build();
}
I have also referred to the following links.
https://github.com/swagger-api/swagger-core/issues/3050
I am able to generate swagger UI if I create a separate class called MultipartBody
with @Schema(type = SchemaType.STRING, format = "binary") and @PartType(MediaType.APPLICATION_OCTET_STREAM)
annotation. But my requirement is to use only MultipartFormDataInput
.
答案1
得分: 5
你差不多就快成功了 只需要在你的RequestBody/Schema
中使用一个专门的类,并告诉OpenAPI忽略方法中的参数。
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@RequestBody(content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA,
schema = @Schema(implementation = MultipartBody.class))
)
@Operation(operationId = "uploadFile")
public Response uploadFile(@Parameter(hidden = true) MultipartFormDataInput input) {
//... 这里是你的逻辑
}
有两点需要注意:@Parameter(hidden = true)
告诉Smallrye OpenAPI在生成模式模型时不考虑你的MultipartFormDataInput
。然后你需要明确地描述模式,使用@RequestBody
,其中MultipartBody
是一个描述所有输入参数的类(如果你想要传递文件载荷以外的其他属性,你也可以在这里添加更多的参数)。
public class MultipartBody {
@FormParam("file")
@Schema(type = SchemaType.STRING, format = "binary", description = "文件数据")
public String file;
@FormParam("fileName")
@PartType(MediaType.TEXT_PLAIN)
public String fileName;
}
请确保MultipartBody
中@FormParam
注解的字段与你期望在MultipartFormDataInput
中找到的“parts”匹配 - 例如,在你的情况下,文件属性应该有@FormParam("attachment")
。
英文:
You were almost there Just use a dedicated class in your RequestBody/Schema and tell OpenAPI ignore the params of your method.
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@RequestBody(content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA,
schema = @Schema(implementation = MultipartBody.class))
)
@Operation(operationId = "uploadFile")
public Response uploadFile(@Parameter(hidden = true) MultipartFormDataInput input) {
//... your logic here
}
Two things to note: @Parameter(hidden = true)
tells Smallrye OpenAPI to not consider your MultipartFormDataInput
when generating Schema model. Then you need to tell describe the schema explicitly, using @RequestBody
, where MultipartBody
is a class that describes all your input params(you can add more params there if you want to for example pass other props along with the file payload)
public class MultipartBody {
@FormParam("file")
@Schema(type = SchemaType.STRING, format = "binary", description = "file data")
public String file;
@FormParam("fileName")
@PartType(MediaType.TEXT_PLAIN)
public String fileName;
}
Just make sure that the @FormParam
annotated fields in the MultipartBody
match the ,,parts" that you expect to find in your MultipartFormDataInput
- e.g. in your case the file attribute should have @FormParam("attachment")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论