2012-01-18 12 views
6

Necesito crear un controlador de carga de archivos como servicio web REST con CXF. He sido capaz de cargar un único archivo con metadatos utilizando código como el siguiente:Carga de múltiples archivos y metadatos con 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(); 
} 

Ahora tengo que añadir soporte para cargar varios archivos en la misma petición. En este caso, en lugar de un archivo adjunto con image/jpeg tipo de contenido, obtengo un archivo adjunto con multipart/mixed tipo de contenido, que a su vez contiene los archivos adjuntos individuales image/jpeg que necesito.

He visto ejemplos para cargar múltiples objetos JSON o JAXB con metadatos, pero no he podido obtener nada para trabajar con datos de imágenes binarias. He intentado utilizar MultipartBody directamente, pero solo devuelve el archivo adjunto multipart/mixed, no los archivos adjuntos image/jpeg incrustados en él.

¿Hay alguna forma de analizar recursivamente un archivo adjunto multipart/mixed para obtener los archivos adjuntos incrustados? Por supuesto, puedo obtener el flujo de entrada del archivo adjunto multipart/mixed, y analizar los archivos yo mismo, pero espero que haya una mejor manera.

ACTUALIZACIÓN

Esto parece kludgey, pero el siguiente fragmento de código es suficiente por ahora. Aunque me encantaría ver una mejor manera.

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

han intentado definir el parámetro como final @Multipart ("imagen") Lista imágenes o es más un problema con los tipos de contenido? – AxelTheGerman

+0

@axel Si agrego una anotación Multipart a la lista de archivos adjuntos, CXF solo pasa un valor nulo. Debo dejarlo sin decoración para obtener las imágenes. –

Respuesta

0

He creado un servicio similar para subir varias imágenes. Mi aplicación tiene el siguiente aspecto (tal vez ayuda)

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

} 

si alguien prefiere matrices bye en lugar de flujos de entrada, que se puede convertir fácilmente el uso de este método de ayuda

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