2012-01-18 15 views
6

Potrzebuję utworzyć procedurę pobierania plików jako usługę WWW REST z CXF. Byłem w stanie przesłać pojedynczy plik z metadanych przy użyciu kodu jak poniżej:Przesyłanie wielu plików i metadanych za pomocą CXF

@POST 
@Path("/uploadImages") 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
public Response uploadImage(@Multipart("firstName") String firstName, 
     @Multipart("lastName") String lastName, 
     List<Attachment> attachments) { 

    for (Attachment att : attachments) { 
     if (att.getContentType().getType().equals("image")) { 
      InputStream is = att.getDataHandler().getInputStream(); 
      // read and store image file 
     } 
    } 

    return Response.ok().build(); 
} 

Teraz muszę dodać wsparcie dla przesyłania wielu plików w tym samym wniosku. W tym przypadku zamiast załącznika z typem treści image/jpeg otrzymuję załącznik z typem treści multipart/mixed, który sam zawiera indywidualne załączniki, których potrzebuję.

Widziałem przykłady do przesłania wielu obiektów JSON lub JAXB z metadanymi, ale nie udało mi się uzyskać niczego do pracy z danymi binarnymi. Próbowałem używać MultipartBody bezpośrednio, ale zwraca tylko załącznik multipart/mixed, a nie załączniki w nim osadzone.

Czy istnieje sposób na rekursywne zanalizowanie załącznika multipart/mixed w celu pobrania załączników? Mogę oczywiście uzyskać strumień wejściowy z załącznika multipart/mixed i samemu sparsować pliki, ale mam nadzieję, że jest lepszy sposób.

UPDATE

Wydaje kludgey, ale następujący fragment kodu jest wystarczająco dobry na teraz. Chciałbym jednak zobaczyć lepszy sposób.

for (Attachment att : attachments) { 
    LOG.debug("attachment content type: {}", att.getContentType().toString()); 

    if (att.getContentType().getType().equals("multipart")) { 
     String ct = att.getContentType().toString(); 
     Message msg = new MessageImpl(); 
     msg.put(Message.CONTENT_TYPE, ct); 
     msg.setContent(InputStream.class, att.getDataHandler().getInputStream()); 
     AttachmentDeserializer ad = new AttachmentDeserializer(msg, Arrays.asList(ct)); 
     ad.initializeAttachments(); 

     // store the first embedded attachment 
     storeFile(msg.getContent(InputStream.class)); 

     // store remaining embedded attachments 
     for (org.apache.cxf.message.Attachment child : msg.getAttachments()) { 
      storeFile(child.getDataHandler().getInputStream()); 
     } 
    } 
    else if (att.getContentType().getType().equals("image")) { 
     storeFile(att.getDataHandler().getInputStream()); 
    } 
} 
+0

Próbowałeś zdefiniować parametr jak końcowe @Multipart ("obraz") Lista obrazów czy jest to większy problem z typami treści? – AxelTheGerman

+0

@axel Jeśli dodaję adnotację wieloczęściową do listy załączników, CXF po prostu przekazuje wartość pustą. Muszę zostawić to bez ozdoby, aby uzyskać obrazy. –

Odpowiedz

0

Zbudowałem podobną usługę do przesyłania wielu zdjęć. Moja implementacja wygląda następująco (może to pomaga)

@Consumes({MediaType.MULTIPART_FORM_DATA,"multipart/mixed" }) 
public Response uploadImages(final List<Attachment> attachments) { 

    Map<String, InputStream> imageMap = new HashMap<String, InputStream>(); 

    for (Attachment attachment : attachments) { 
     String imageName = attachment.getContentDisposition().getParameter("filename"); 
     if (imageName == null) { 
      imageName = UUID.randomUUID().toString(); 
     } 

     InputStream image = attachment.getDataHandler().getInputStream(); 
     imageMap.put(imageName, image); 
    } 

    return imageMap; 

} 

jeśli ktoś preferuje tablice bye zamiast strumienie wejściowe, to można ją przekształcić łatwo za pomocą tej metody pomocnika

private static byte[] extractByteArray(final InputStream inputStream) throws IOException { 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

    byte[] dataChunk = new byte[1024 * 16]; 
    int numRead = 0; 
    while (numRead != -1) { 
     numRead = inputStream.read(dataChunk, 0, dataChunk.length); 

     if (numRead != -1) { 
      buffer.write(dataChunk, 0, numRead); 
     } 
    } 

    buffer.flush(); 
    return buffer.toByteArray(); 
} 
Powiązane problemy