【问题标题】:Uploading large file using Jersey on backend在后端使用 Jersey 上传大文件
【发布时间】:2014-09-03 03:44:15
【问题描述】:

我运行一个允许上传文件的简单后端应用程序。我使用 Jersey 并在 Jetty 中运行它。我的代码如下所示:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@Context UriInfo uriInfo, FormDataMultiPart multipart, @Context  HttpServletRequest httpRequest) {
    FormDataBodyPart fileId = multipart.getField("fileId");
    FormDataBodyPart fileSize = multipart.getField("fileSize");
    FormDataBodyPart file = multipart.getField("file");

    ContentDisposition cd = file.getContentDisposition();
    String fileName = cd.getFileName();
    long size = Long.valueOf(fileSize.getValue());
    ...

Upload 工作得很好,但我发现只有在整个流上传到后端时才调用该方法。因此,例如,如果我发送大文件(要上传 3Gig),我的 POST 请求会立即出现在后端,但只有当整个 3Gig 通过网络上传时才会调用上述方法。

我想在方法中做一些检查,在某些情况下不上传文件,所以它不需要将整个内容传递给后端,然后将错误消息发送回来。

如何避免将整个文件内容上传到后端,但在我开始从数据流中读取之前调用该方法?

【问题讨论】:

  • 您要进行哪些检查?我认为您无法检查 MultiPart 实体 - IE fileId 中的任何内容,因为这需要首先传输整个实体。
  • @Will,我想做一些限制检查,所以如果文件大小超过某个值或在一段时间内进行了多次上传,请不要接受文件。实际上我最近几天做了一些研究,看起来在整个多部分实体被消耗之前没有办法发送响应:(。它与 Jetty 无关,但与 HTTP...

标签: java jersey jetty


【解决方案1】:

最终我使用了 2 个连续的 POST 来解决这个问题,客户端应该使用 2 个连续的 POST 来上传这么大的文件:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response newUpload(@Context UriInfo uriInfo, FormDataMultiPart multipart,
        @Context HttpServletRequest httpRequest) {
    FormDataBodyPart fileSize = multipart.getField("fileSize");
    long size = Long.valueOf(fileSize.getValue());
    if (!checkSizeLimits(size)) {
        return Response.status(Status.BAD_REQUEST).build();
    }
    // here comes some code which generates an unique id and its URI for the data
    ...
    return Response.status(Status.CREATED).entity(new FileUploadInfo(uri.toString())).build();
}

@POST
@Path("/{fileId}")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@Context UriInfo uriInfo, FormDataMultiPart multipart,
        @Context HttpServletRequest httpRequest, @PathParam("fileId") String fileId) {
    FormDataBodyPart fileSize = multipart.getField("fileSize");
    FormDataBodyPart file = multipart.getField("file");
    //...
    return Response.status(Status.CREATED).entity(new FileUploadInfo(uri.toString())).build();
 }

看起来很难看,但比在数据流完全加载后进行文件大小检查要好。因此,客户端应该首先对 newUpload() 方法进行 POST 调用,提供文件大小。如果大小合适,则响应包含用于流式传输文件数据的第二个 POST 的 URI。第二种方法可以再次进行文件大小检查(未提供),以确保初始 POST 具有相同的文件大小字段。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
相关资源
最近更新 更多