tutorial example español documentar java rest jersey swagger swagger-ui

java - example - swagger tutorial español



¿Cómo configurar Swagger UI, Jersey y cargar archivos? (2)

Tengo un servicio de Jersey con un método de carga de archivos que se ve así (simplificado):

@POST @Path("/{observationId : [a-zA-Z0-9_]+}/files") @Produces({ MediaType.APPLICATION_JSON}) @Consumes(MediaType.MULTIPART_FORM_DATA) @ApiOperation( value = "Add a file to an observation", notes = "Adds a file to an observation and returns a JSON representation of the uploaded file.", response = ObservationMediaFile.class ) @ApiResponses({ @ApiResponse(code = 404, message = "Observation not found. Invalid observation ID."), @ApiResponse(code = 406, message= "The media type of the uploaded file is not supported. Currently supported types are ''images/*'' where ''*'' can be ''jpeg'', ''gif'', ''png'' or ''tiff'',") }) public RestResponse<ObservationMediaFile> addFileToObservation( @PathParam("observationId") Long observationId, @FormDataParam("file") InputStream is, @FormDataParam("file") FormDataContentDisposition fileDetail, @FormDataParam("fileBodyPart") FormDataBodyPart body ){ MediaType type = body.getMediaType(); //Validate the media type of the uploaded file... if( /* validate it is an image */ ){ throw new NotAcceptableException("Not an image. Get out."); } //do something with the content of the file try{ byte[] bytes = IOUtils.toByteArray(is); }catch(IOException e){} //return response... }

Funciona y puedo probarlo con éxito utilizando la extensión de Postman en Chrome.

Sin embargo, Swagger ve 2 parámetros llamados "archivo". De alguna manera parece entender que el parámetro InputStream y el parámetro FormDataContentDisposition son en realidad 2 partes del mismo parámetro de file , pero no lo ve para el parámetro FormDataBodyPart .

Este es el JSON de Swagger para los parámetros:

parameters: [ { name: "observationId", required: true, type: "integer", format: "int64", paramType: "path", allowMultiple: false }, { name: "file", required: false, type: "File", paramType: "body", allowMultiple: false }, { name: "fileBodyPart", required: false, type: "FormDataBodyPart", paramType: "form", allowMultiple: false }]

Como resultado, Swagger UI genera un campo selector de archivos y un campo de texto adicional para el argumento FormDataBodyPart:

Entonces, cuando selecciono un archivo y envío el formulario en Swagger UI, termino leyendo el contenido del campo de texto en InputStream en lugar del contenido del archivo cargado. Y si dejo el campo de texto vacío, obtengo el nombre del archivo.

¿Cómo puedo ordenarle a Swagger que ignore el parámetro FormDataBodyPart?

Alternativamente, como solución alternativa, ¿cómo puedo obtener el tipo de medio del archivo cargado sin el objeto FormDataBodyPart?

Uso Jersey 2.7 y swagger-jersey2-jaxrs_2.10 versión 1.3.4.


Crea un filtro swagger para Jersey y luego marca el parámetro como interno o alguna otra cadena sobre la que estés filtrando. Esto también se muestra en este ejemplo:

https://github.com/wordnik/swagger-core/blob/master/samples/java-jaxrs/src/main/java/com/wordnik/swagger/sample/util/ApiAuthorizationFilterImpl.java

Su método de servicio tendrá esta anotación de parámetro

@ApiParam(access = "internal") @FormDataParam("file") FormDataBodyPart body,

Su filtro lo buscará así:

public boolean isParamAllowed(Parameter parameter, Operation operation, ApiDescription api, Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) { if ((parameter.paramAccess().isDefined() && parameter.paramAccess().get().equals("internal"))) return false; else return true; }

Registre su filtro swagger para jersey y luego no devolverá ese campo y swagger-ui no lo mostrará, lo que solucionará su problema de carga.

<init-param> <param-name>swagger.filter</param-name> <param-value>your.company.package.ApiAuthorizationFilterImpl</param-value> </init-param>


No está claro cuándo se agregó a Jersey, pero una nota al final de la sección Multiparte dice "la anotación @FormDataParam también se puede usar en los campos ". Efectivamente, puedes hacer esto:

@FormDataParam(value="file") FormDataContentDisposition fileDisposition; @FormDataParam("fileBodyPart") FormDataBodyPart body; @Path("/v1/source") @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces({ MediaType.APPLICATION_JSON}) @ApiOperation( value = "Create a new Source from an uploaded file.", response = Source.class ) public Response makeSource( @FormDataParam(value="file") InputStream inputStream ) { logger.info(fileDisposition.toString()); return makeSourceRaw(inputStream, fileDisposition.getFileName()); }

Esto proporciona el FormDataContentDisposition pero lo convierte en "invisible" para Swagger.

Actualización : esto funciona, pero no si hay otros recursos definidos (anotaciones @Path) que no toman FormDataContentDisposition. Si hay, entonces Jersey falla en tiempo de ejecución porque no puede completar el campo de archivo de presentación.

Una mejor solución si está usando una versión reciente de Swagger para simplemente marcar el parámetro como oculto como tal.

@FormDataParam("fileBodyPart") FormDataBodyPart body; @Path("/v1/source") @POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces({ MediaType.APPLICATION_JSON}) @ApiOperation( value = "Create a new Source from an uploaded file.", response = Source.class ) public Response makeSource( @FormDataParam(value="file") InputStream inputStream, @ApiParam(hidden=true) @FormDataParam(value="file") FormDataContentDisposition fileDisposition; ) { logger.info(fileDisposition.toString()); return makeSourceRaw(inputStream, fileDisposition.getFileName()); }