Загрузка нескольких файлов и метаданных с помощью CXF - PullRequest
6 голосов
/ 18 января 2012

Мне нужно создать обработчик загрузки файлов в качестве веб-службы REST с 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();
}

Теперь мне нужно добавить поддержку загрузки нескольких файлов в одном запросе.В этом случае вместо вложения с типом контента image/jpeg я получаю вложение с типом контента multipart/mixed, которое само содержит нужные мне вложения image/jpeg.

Я видел примерыдля загрузки нескольких объектов JSON или JAXB с метаданными, но я не смог заставить что-либо работать с двоичными данными изображений.Я пытался использовать MultipartBody напрямую, но он возвращает только вложение multipart/mixed, а не вложенные в него image/jpeg.

Есть ли способ рекурсивного анализа вложения multipart/mixed для получения встроенноговложения?Конечно, я могу получить входной поток вложения multipart/mixed и разобрать файлы самостоятельно, но я надеюсь, что есть лучший способ.

ОБНОВЛЕНИЕ

Это кажется хитрым, но следующий фрагмент кода пока достаточно хорош.Хотелось бы увидеть лучший способ.

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

1 Ответ

0 голосов
/ 04 апреля 2012

Я создал аналогичный сервис для загрузки нескольких изображений. Моя реализация выглядит следующим образом (может быть, это помогает)

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

}

если кто-то предпочитает массивы пока, а не входные потоки, его можно легко преобразовать с помощью этого вспомогательного метода

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