当前位置: 首页 > 知识库问答 >
问题:

Jersey服务文件上载导致OutOfMemoryError

洪通
2023-03-14

我正在用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>

表格提交请求

POST /nbs/v2/upload HTTP/1.1
Host: 127.0.0.1:8080
Cache-Control: no-cache
Postman-Token: a4c1d4e9-5f71-2321-3870-e9cac0524f8d
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryA2Z9pPMA7y3da8BG

------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="account-sid"

Q45Ppm5ukvdqjTQ6eW0O5ztTXipwnjKQx1p6cf+fbCQ=
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="api-token"

6397cd691909fdc14cef67dbc1dc2dc3
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="file"; filename="screen_4_100155.jpg"
Content-Type: image/jpeg

......Exif..MM.*.............................b...........j
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="checksum"

6a3381b1d16bded4a3dfc325a8bb800e
------WebKitFormBoundaryA2Z9pPMA7y3da8BG

JVM堆大小

-Xmx=1024mb

上载约50MB的文件时,会在名为FileBackedOutputStream7949386530699987086的目录下创建两个MD5和相似的临时文件。tmp和MIME8234229766850016150。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)

并删除名为mime823422976850016150的文件。tmp离开另一个。和取消删除的FileBackedOutputStream。。。。tmp文件占据了硬盘上的全部空间。

>

  • 将堆空间增加到7GB,但无法上传~200MB文件。

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

    创建文件名jersey-multipart-config.properties和内容

    球衣。配置。多部分。缓冲阈值=-1

    文件MIME[随机数]. tmp不再创建,但FileBackedOutputStream[随机数]. tmp仍然挂在硬盘上,除非重新启动tomcat。

    >

  • 泽西如何处理大文件(也许1GB)而不在我的硬盘上留下临时文件?最好的情况是根本不使用硬盘驱动器并通过内存传输小块。

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

    • 到目前为止我找到的最接近的解释。阅读
    • 这家伙也有类似的问题,但在客户端。阅读
    • 可能包含解决方案,但无法理解答案。阅读
    • 很接近我的问题,但无法解决。阅读
    • bufferThreshold的想法来自这里。阅读
  • 共有1个答案

    万俟亦
    2023-03-14

    通过在我的web中添加以下行,问题#1似乎得到了解决。在<代码>

    <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>
    

    并删除了jersey multipart配置。属性文件。

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

    但我仍然无法解释问题2。

     类似资料:
    • 我正在开发一个android应用程序,我试图将谷歌驱动器集成到我的应用程序中。该程序是允许同步,所以它在SD卡上创建一个文件,然后这个文件被上传到谷歌驱动器上。我成功地进行了身份验证,但是当我使用函数上传时,我得到一个NullPointerException,并且我看不到值在哪里是null,因为当我遍历所有内容时,似乎没有任何内容是null。 下面是我用来执行上传的代码。 以下是我如何获得驱动器服

    • 我想通过上载一个图像和员工数据在系统中创建一个员工信息。我可以使用Jersey使用不同的rest调用。但我想在一次rest调用中实现。我提供了下面的结构。请帮我在这方面怎么做。 每当我试图做,我得到错误在Chrome邮差。下面给出了我的Employee json的简单结构。

    • 我正在尝试上传一个图像。当我从本地主机上进行时,它工作得很好,但当我发布它时,它从服务器上抛出一个错误: 当我使用此代码时: 错误为: System.io.DirectoryNotFoundException:找不到路径“d:\inetpub\vhosts\xx.com\httpdocs\images\sections\developer\clientlogo\demo.png”的一部分。在sys

    • 我想上传一个文件到不同的服务器使用卷曲。我读过许多类似的问题,但我没有得到任何解决我的问题。下面是我现在得到的代码: 当我运行此脚本时,它将保持运行200秒,并以以下方式响应: Sep 17 20:56:58 xxxxx vsftpd[2613]:[user]确定登录:客户端“yyyyy” Sep 17 20:56:58 xxxxx vsftpd[2618]:[用户]FTP响应:客户端“YYYYY

    • 本文向大家介绍Feign实现跨服务文件上传下载,包括了Feign实现跨服务文件上传下载的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Feign实现跨服务的文件上传下载操作,供大家参考,具体内容如下 1、跨服务文件上传,目前feign不支持调用文件上传接口,需要自行配置来满足feign的调用方式 ①.首先需要在pom文件里添加feign依赖 ②.上传的接口 ③.添加配置来满足feig

    • 我正在尝试通过Multer将文件上载到服务器。这段代码所做的只是创建文件夹,而不是文件。我还尝试使用github上的教程,但在前端我的代码也没有成功 代码AJAX 还有MAIN.JS 我从前端获得的console.log输出: