File upload Jersey服务文件上载导致OutOfMemoryError

File upload Jersey服务文件上载导致OutOfMemoryError,file-upload,jersey,multipartform-data,heap-memory,File Upload,Jersey,Multipartform Data,Heap Memory,我正在用Jersey 2.0开发表单提交服务。表单包括几个文本字段和一个文件字段。我需要提取文件、文件名、文件媒体类型和文件内容类型,并将它们保存在对象存储中 @Path("upload") @Consumes({MediaType.MULTIPART_FORM_DATA}) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public class UploadService { @POST p

我正在用Jersey 2.0开发表单提交服务。表单包括几个文本字段和一个文件字段。我需要提取文件、文件名、文件媒体类型和文件内容类型,并将它们保存在对象存储中

@Path("upload")
@Consumes({MediaType.MULTIPART_FORM_DATA})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class UploadService {
    @POST
    public BlobDo uploadFile(FormDataMultiPart uploadedBody) {
        String accountSid = uploadedBody.getField("account-sid").getValue();
        String apiToken = uploadedBody.getField("api-token").getValue();
        String checksum = uploadedBody.getField("checksum").getValue();

        FormDataBodyPart bodyPart = uploadedBody.getField("file");
        MySwiftObject obj = new MySwiftObject(bodyPart.getValueAs(InputStream.class));
        obj.setName(bodyPart.getContentDisposition().getFileName());
        obj.setContentType(bodyPart.getMediaType().toString());
        obj.setContentDisposition(bodyPart.getContentDisposition().toString());
   ...
}
pom.xml

<jersey.version>2.17</jersey.version>

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-inmemory</artifactId>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-server</artifactId>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-bean-validation</artifactId>
</dependency>
JVM堆大小

-Xmx=1024mb

问题 上载~50MB文件时,将在目录
/tmp/tomcat7-tomcat7-tmp
中创建两个具有类似MD5总和的临时文件,其名称为
FileBackedOutputStream7949386530699987086.tmp
mime8234229768500150.tmp

在上传完成之前,服务器抛出异常

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.OutOfMemoryError: Java heap space org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:421) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:222) javax.servlet.ServletException:org.glassfish.jersey.server.ContainerException:java.lang.OutOfMemoryError:java堆空间 org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:421) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:222) 并删除名为
mime823422976668500150.tmp的文件,但保留另一个文件。和未删除的
FileBackedOutputStream…tmp
文件填满了硬盘上的整个空间


我所做的
  • 将堆空间增加到7GB,但无法上载约200MB的文件

  • 在服务器上运行作业以删除旧的临时文件

  • 创建了名为
    jersey multipart config.properties
    和内容的文件

    jersey.config.multipart.bufferThreshold=-1

  • 文件
    MIME[random numbers].tmp
    不再创建,但
    FileBackedOutputStream[random numbers].tmp
    仍然挂起在硬盘上,除非tomcat重新启动


    问题:
  • Jersey如何处理大文件(可能1GB),而不在硬盘上留下临时文件?最好的情况是根本不使用硬盘,而是通过内存传输小块数据

  • 如果输入流以文件备份,为什么会出现堆溢出


  • 我读的材料
    • 到目前为止,我找到了一个很好的解释
    • 这家伙也有类似的问题,但在客户端
    • 可能包含解决方案,但无法理解答案
    • 很接近我的问题,但无法解决
    • 我的想法就是从这里开始的
    问题1似乎是通过在my web.xml的
    标记下添加以下行解决的

    <multipart-config>
            <location>/tmp</location>
            <max-file-size>1000000000</max-file-size>
            <max-request-size>1500000000</max-request-size>
            <file-size-threshold>0</file-size-threshold>
    </multipart-config>
    
    
    /tmp
    1000000000
    1500000000
    0
    
    并删除了
    jersey multipart config.properties
    文件

    现在我可以上传超过200Mb的文件了。不再创建任何临时文件

    但我仍然无法解释问题2

    <multipart-config>
            <location>/tmp</location>
            <max-file-size>1000000000</max-file-size>
            <max-request-size>1500000000</max-request-size>
            <file-size-threshold>0</file-size-threshold>
    </multipart-config>