如何使用jersey-client V2.13(从客户端到服务器)在JAVA上传750MB的文件?

时间:2014-10-26 17:01:35

标签: java rest file-upload jersey jersey-client

在开始向您解释我的问题之前,我想与您分享我使用的库版本和服务器:

javax.ws.rs-api: 2.0.1
jersey-container-servlet: 2.13
jersey-media-multipart: 2.13
jackson: 2.4.3  

I also use Apache Tomcat Server version 7.0.55. 

所以我在下面编码:

    /**
     * On the client side.
     */
public void uploadAFile() {
    Client client = ClientBuilder.newBuilder()
            .register(MultiPartFeature.class)
            .build();

    WebTarget target = null;
    try {
        target = client
                .target("https://blo-bla.rhcloud.com/rest")
                .path("v1").path("upload");
    } catch (IllegalArgumentException | NullPointerException e) {
        LOG_TO_CONSOLE.fatal(e, e);
        LOG_TO_FILE.fatal(e, e);
    }

    Builder builder = target.request(MediaType.TEXT_PLAIN);
    builder.header("Authorization",
    getValidBasicAuthenticationStrEncrypted());

    FormDataMultiPart form = new FormDataMultiPart();
    form.field("anotherParam", "Bozo");

    String fileName = "/Users/drizzy/Documents/Divx/CaseDepartFolder/sample.avi";

    File file = new File(fileName);
    form.bodyPart(new FileDataBodyPart("file", file,
            MediaType.APPLICATION_OCTET_STREAM_TYPE));

    Response response = builder.post(Entity.entity(form,
            MediaType.MULTIPART_FORM_DATA_TYPE));

    LOG_TO_CONSOLE.debug(response.getStatus());
    LOG_TO_CONSOLE.debug(response.readEntity(String.class));
}


   /**
     * On the server side.
     */
    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @Produces(MediaType.TEXT_PLAIN)
    public String uploadFile(@FormDataParam("file") InputStream fileInputStream,
                             @FormDataParam("file") FormDataContentDisposition fileDisposition,
                             @FormDataParam("anotherParam") String str) 
                             throws FileNotFoundException, IOException 
    {
        System.out.println("str: " + str);
        final String basePath = "/Users/drizzy/eclipse-workspace/tomcat7jbossews"
                                + "/src/main/resources/uploads/";

        final String fileName = fileDisposition.getFileName();
        System.out.println(new StringBuilder().append("***** fileName ")
                                              .append(fileName)
                                              .toString());

        final String filePath = new StringBuilder().append(basePath)
                                                   .append(fileName)
                                                   .toString();
        System.out.println(filePath);

        try (OutputStream fileOutputStream = new FileOutputStream(filePath)) {
            int read = 0;
            final byte[] bytes = new byte[1024];
            while ((read = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, read);
            }
        }

        return "File Upload Successfully !!";
    }

在客户端产生这些例外:

Java Heap space error 

Java binding Exception: Already connected

所以我的问题是要知道是否有人可以使用jersey-client V2.13向客户端提供代码示例,该客户端将客户端上的大文件上传到服务器?或者甚至可以告诉我上面的代码有什么问题?

注意:我只想使用jersey-client V2.13来处理这个问题,所以请不要使用第三方库或不使用jersey-client V2.13的解决方案。

2 个答案:

答案 0 :(得分:1)

最后我找到了解决问题的方法:

1 - 用于修复"已连接"异常。

Java 7引入了默认启用的SNI支持。我发现某些配置错误的服务器会发送一个"无法识别的名称" SSL握手中的警告被大多数客户端忽略...除了Java。正如@Bob Kerns所提到的,Oracle工程师拒绝修复"这个错误/功能。

作为解决方法,他们建议设置jsse.enableSNIExtension属性。要允许您的程序无需重新编译即可运行,请将您的应用程序运行为:

"-Djsse.enableSNIExtension=false"

此信息的来源here

该属性也可以在Java代码中设置,但必须在任何SSL操作之前设置。加载SSL库后,您可以更改属性,但不会对SNI状态产生任何影响。要在运行时禁用SNI(具有上述限制),请使用:

System.setProperty("jsse.enableSNIExtension", "false");

2 - 用于修复chunkedTransferMode的激活和java堆空间错误。

Java堆空间错误:我不得不增加客户端使用的jvm内存:

为了做到这一点在日食中,转到Run>运行配置...>选择客户端类>参数> VM参数:

-Xms1024m -Xmx2500m -XX:+PrintFlagsFinal

我自己用来修复该问题的来源:source 1source 2source 3

关于启用chunkedTransferMode的事实,我不需要这样做,因为我在jersey-client的文档中发现默认情况下在jersey-client V2.13中启用了chunkedTransferMode。

最后,我们将这些参数传递给客户端的JVM:

"-Djsse.enableSNIExtension=false" "your classes ..." -Xms1024m -Xmx2500m -XX:+PrintFlagsFinal

答案 1 :(得分:0)

好吧,似乎问题是一个非常大的文件(350Mb),你正在达到各种限制。因此,我建议以不同的方式解决问题。

可能的解决方案:

  1. 在客户端上拆分文件,然后通过"较小的"上传文件。零件到服务器,按原始顺序组装回来。
  2. 将文件流式传输到服务器:http://commons.apache.org/proper/commons-fileupload/streaming.html
  3. 我更喜欢2.解决方案,因为它可能是最容易实现的。 希望这会有所帮助。