使用 Jersey 在 REST 服务中上传多个文件
Multiple files upload in a REST service using Jersey
这里有很多链接建议使用 multipart/form-data
以及如何在此处上传文件。对于通过 CURL 命令上传的多个文件和接受 FormDataMultiPart
的 REST 服务的组合,无法真正找到一个。
服务中的代码目前看起来像:
@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。
我在这里错过了什么愚蠢的事情吗?
尝试为每个多部分条目使用单独的 -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)
。这将为您提取的每个部分提供 [=21=]。如果您希望该部分作为 InputStream
,您可以使用 FormDataBodyPart#getValueAs(InputStream.class)
获取数据,或者您可以使用 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
.
中获取有关零件的信息,例如文件名
另见
- Why “FormDataMultiPart” type parameter is treated differently
- Jersey documentation for its multipart support (on the server side)
- File upload along with other object in Jersey restful web service
脚注
零件也可以有相同的名称,例如
-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) { ... }
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 }
这里有很多链接建议使用 multipart/form-data
以及如何在此处上传文件。对于通过 CURL 命令上传的多个文件和接受 FormDataMultiPart
的 REST 服务的组合,无法真正找到一个。
服务中的代码目前看起来像:
@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。
我在这里错过了什么愚蠢的事情吗?
尝试为每个多部分条目使用单独的 -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)
。这将为您提取的每个部分提供 [=21=]。如果您希望该部分作为 InputStream
,您可以使用 FormDataBodyPart#getValueAs(InputStream.class)
获取数据,或者您可以使用 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
.
另见
- Why “FormDataMultiPart” type parameter is treated differently
- Jersey documentation for its multipart support (on the server side)
- File upload along with other object in Jersey restful web service
脚注
零件也可以有相同的名称,例如
-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) { ... }
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 }