Здесь довольно много ссылок, которые предлагают использовать 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.
Что-нибудь глупое, что я пропустил здесь?
Вы не используете @FormDataParam
, когда используете FormDataMultiPart
. FormDataMultiPart
— тело запроса весь (части все). Вы используете @FormDataParam
, когда хотите получить детали индивидуальный, где вы должны использовать имя детали в качестве значения аннотации. Возможно, это может дать некоторые разъяснения. Также посмотрите на Документы Джерси для Multipart
@PaulSamsotha Большое спасибо за ответ. Я бы посмотрел документацию через некоторое время, хотя я мог бы на минимальном примере убедиться, что удаление @FormDataParam
работает, добавляя ценность multiPart
.
Попробуйте использовать отдельный флаг -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
.
Части также могут иметь одно и то же имя, например.
-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
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 }
образец предложения онлайн для использования
FormDataMultiPart
, поскольку я начинаю задаваться вопросом, поддерживается ли это вообще как-то.