2014-04-17 33 views
5

Ben bu (basitleştirilmiş) benzeyen bir dosya yükleme yöntemi ile bir Jersey hizmeti:Swagger UI, Jersey ve dosya yükleme nasıl yapılandırılır?

@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... 
} 

O inşaat ve bunu başarıyla Chrome'da Postacı uzantısını kullanarak test edebilirsiniz. Bununla birlikte, Swagger "dosya" adlı 2 parametreyi görmektedir. Her nasılsa, InputStream parametresi ve FormDataContentDisposition parametresinin aslında aynı file parametresinin 2 kısmı olduğunu anlıyor görünmektedir, ancak FormDataBodyPart parametresi için bunu görememektedir.

Bu

parametreler için Swagger JSON geçerli:

swagger ui

: Sonuç olarak

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 
}] 

, Swagger UI FormDataBodyPart argüman için bir dosya seçici alanını ve ekstra bir metin alanını oluşturur

Bir dosya seçtiğimde ve formu Swagger UI'ye gönderdiğimde, yüklenen dosyanın içeriği yerine InputStream içindeki metin alanının içeriğini okuyorum. Ve eğer metin alanını boş bırakırsam, dosyanın adını alırım.

Swagger'ın FormDataBodyPart parametresini yoksaymasını nasıl önleyebilirim?

Alternatif olarak, bir çalışma çevresinde, yüklenen dosyanın ortam türünü FormDataBodyPart nesnesi olmadan nasıl edinebilirim?

Jersey 2.7 ve swagger-jersey2-jaxrs_2.10 sürüm 1.3.4 kullanıyorum.

+1

Bu dosya yükleme jersey1 ile mümkün olup olmadığını bilen var mı? (1.19 kullanıyorum) Her nasılsa, çok parçalı/form vermeme sahip olmamasına rağmen, dosya yüklemesini işleyemiyorum. Ayrıca Parametreler içinde "gövde" olarak değil "dosya" olarak gösterilir – dominicbri7

cevap

4

Forma için bir süzgeç filtresi oluşturun ve ardından parametreyi dahili veya filtrelediğiniz başka bir dize olarak işaretleyin. Bu aynı zamanda bu örnekte gösterilmiştir:

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

Servis yöntem bu parametre ek açıklama

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

Filtreniz Şöyle arayacaktır:

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; 
} 

Kayıt senin jersey için swagger filtresi ve daha sonra bu alana geri dönmeyecek ve swagger-ui, yükleme sorununuzu çözecek olanı göstermeyecektir. Bu Jersey eklendi ama Çok parçalı bölümün en sonuna bir not "@FormDataParam açıklama da alanlar kullanılabilir" dediğinde

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

Teşekkür etti çalıştı. Kodumda swagger'a daha fazla bağımlılık katmak istemiyorum, ama problemi çözdüm, bu yüzden içeriğim. –

+0

Merhaba @PierreHenry Ayrıca maven eklentisini kullanarak swagger json üretiyorum, ama java.io.InputStream java.io.File türünde değil. Bu hatayı hiç aldın mı? – Samra

+0

Üzgünüm, bu uzun zaman önceydi ve hatırlayamıyorum. Sanırım yeni bir soru sormaktan daha iyi olur. –

1

Belli değil. Tabii ki bunu yapabilirsiniz:

@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()); 
} 

Bu FormDataContentDisposition sağlar ama Swagger için o "görünmez" hale getirir.

Güncelleştirmesi: Bu, FormDataContentDisposition'ı almayan başka kaynakların (@Path ek açıklamaları) bulunması durumunda işe yarar. Eğer varsa, Jersey çalışma zamanında dosya başarısız olur, çünkü dosyaDisposition alanını dolduramaz.

Parametreyi yalnızca gizli olarak işaretlemek için yeni bir Swagger sürümünü kullanıyorsanız daha iyi bir çözüm.

@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()); 
}