Загрузка нескольких файлов в службу REST с использованием Джерси

Здесь довольно много ссылок, которые предлагают использовать multipart/form-data и как загрузить файл здесь. Не удалось найти его для комбинации нескольких файлов, загруженных с помощью команды CURL, и в службу REST, принимающую FormDataMultiPart.

Код в обслуживании в настоящее время выглядит так:

@javax.ws.rs.POST
@javax.ws.rs.Path("/sample-bulk")
@javax.ws.rs.Consumes(javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA)
public javax.ws.rs.core.Response bulkUpload(@FormDataParam("file") org.glassfish.jersey.media.multipart.FormDataMultiPart multiPart) {
    log.info("{} log", multiPart.getField("file"));
    return Response.ok().build();
}

и CURL, который я пытаюсь вызвать, выглядит следующим образом:

curl -X POST "http://localhost:37200/api/sample-bulk" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@/Users/naman/Desktop/Media/video.mp4;type=video/mp4"

Но в результате multiPart оказывается null на службе и, конечно же, NPE.

Что-нибудь глупое, что я пропустил здесь?

образец предложения онлайн для использования FormDataMultiPart, поскольку я начинаю задаваться вопросом, поддерживается ли это вообще как-то.

Naman 09.07.2019 20:15

Вы не используете @FormDataParam, когда используете FormDataMultiPart. FormDataMultiPart — тело запроса весь (части все). Вы используете @FormDataParam, когда хотите получить детали индивидуальный, где вы должны использовать имя детали в качестве значения аннотации. Возможно, это может дать некоторые разъяснения. Также посмотрите на Документы Джерси для Multipart

Paul Samsotha 10.07.2019 08:02

@PaulSamsotha Большое спасибо за ответ. Я бы посмотрел документацию через некоторое время, хотя я мог бы на минимальном примере убедиться, что удаление @FormDataParam работает, добавляя ценность multiPart.

Naman 10.07.2019 08:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
3 704
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Попробуйте использовать отдельный флаг -F для каждой составной записи, например:

curl -X POST "http://localhost:37200/api/sample-bulk" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "file=@/Users/naman/Desktop/Media/video.mp4" -F "type=video/mp4"

Ответ принят как подходящий

Проблема с параметром метода (наличие @FormDataParam)

public Response bulkUpload(@FormDataParam("file") FormDataMultiPart multiPart) {}

@FormDataParam используется, когда вы хотите, чтобы декларативно извлекала отдельные части из составного запроса, тогда как FormDataMultiPart используется для получения всего составного тела, а программно извлекает каждую часть. Это возможно, чтобы иметь вложенную составную часть, где полная составная часть является отдельной частью (в этом случае то, что у вас есть, будет работать), но здесь это не так.

Если вы удалите @FormDataParam("file"), то он будет работать как положено. Вы можете начать извлекать части из составного, используя метод, который вы используете getField(fieldName). Это даст вам FormDataBodyPart за каждую извлеченную часть. Вы можете получить данные с помощью FormDataBodyPart#getValueAs(InputStream.class), если хотите, чтобы эта часть была InputStream, или вы можете использовать File.class или byte[].class, в зависимости от ваших предпочтений. Вот как можно извлечь данные из файла FormDataMultiPart.

Каждая часть имеет свое имя, и вы извлекаете часть, используя это имя. В случае вашего запроса cURL вы отправили одну часть, и имя этой части — file. то есть "file=@/Users/...". Так что если вы хотите отправить другую часть, просто добавьте еще один параметр с другим именем1, по словам Владимира:

curl -X POST "http://localhost:37200/api/sample-bulk"\
     -H "accept: application/json"\
     -H "Content-Type: multipart/form-data"\
     -F "file1=@/Users/naman/Desktop/Media/video.mp4"\
     -F "file2=@/Users/naman/Desktop/Media/another_video.mp4"

Как я упоминал ранее, @FormDataParam используется для декларативного извлечения частей. Вы используете имя детали в качестве значения аннотации. Так что с предыдущей командой cURL вы могли бы сделать.

public Response bulkUpload(
        @FormDataParam("file1") InputStream file1,
        @FormDaraParam("file1") FormDataContentDisposition file1Fdcd,
        @FormDataParam("file2") InputStream file2,
        @FormDaraParam("file2") FormDataContentDisposition file2Fdcd) {
}

Вы можете получить информацию о части, такую ​​как имя файла, из FormDataContentDisposition.

Смотрите также


Сноски

  1. Части также могут иметь одно и то же имя, например.

    -F file=@path_to_file1
    -F file=@path_to_file2
    

    По этой причине, когда вы пытаетесь получить часть программно, вы получаете список FormDataBodyParts вместо одного объекта, т.е.

    FormDataMultiPart multiPart = ...
    List<FormDataBodyPart> files = multiPart.getField("file");
    

    И если бы вы хотели получить их декларативно, вы бы использовали List вместо одного типа объекта.

    public Response upload(@FormDataParam("file") List<InputStream> files) { ... }
    

Я использую так, как вы хотите обрабатывать multipart. Я сделал formData.append('file', file.name, file.data); formData.append('testObj', JSON.stringyfy(testObj)) в файле service.ts. И использовал multipart в REST, чтобы получить «testObj» и «файл», но получил NPE

Geek 16.07.2020 19:28
Use this parameter 

public Response uploadFile(@FormDataParam("files") List<FormDataBodyPart> file) 

Use for loop

 for (int j = 0; j < files.size(); j++) {
   FormDataBodyPart this_formDataBodyPartFile = files.get(j);
   ContentDisposition this_contentDispositionHeader = this_formDataBodyPartFile
                                                    .getContentDisposition();
   InputStream this_fileInputStream = this_formDataBodyPartFile.getValueAs(InputStream.class);
                                            FormDataContentDisposition fileDetail = (FormDataContentDisposition) this_contentDispositionHeader;

//Write the code upload code   }

Другие вопросы по теме