2014-10-26 39 views
0

剛開始解釋你我的問題之前,我想與大家分享,我使用圖書館的版本和服務器:如何使用jersey-client V2.13(從客戶端到服務器)以JAVA方式上傳750MB文件?

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的代碼示例向客戶端上傳大文件?甚至可以告訴我上面的代碼中有什麼問題?

注意:我只想使用澤西客戶端版本V2.13來處理這個問題,所以請不要使用第三方庫或者不使用澤西客戶端版本V2.13的解決方案。

+0

你在「大文件」明白什麼?包括Tomcat在內的大多數服務器都有限制(在配置中)上傳時文件的大小。 – Drejc 2014-10-26 17:23:29

+0

如果服務器有限制並且您不想更改它,則會卡住。如何改變它取決於框架,而不是容器:沒有一種通用技術。 – EJP 2014-10-26 19:32:56

+0

錯誤的是什麼?我在這裏沒有說錯。 – EJP 2014-10-26 20:20:32

回答

1

最後,我已經找到了解決我的問題:

1 - 爲了固定「已連接」異常。

Java 7引入了默認啓用的SNI支持。我發現某些配置錯誤的服務器在SSL握手中發送了「無法識別的名稱」警告,大多數客戶端都忽略了這個警告......除了Java。正如@Bob Kerns提到的,Oracle工程師拒絕「修復」這個bug /功能。

作爲解決方法,他們建議設置jsse.enableSNIExtension屬性。爲了讓您的程序,而無需重新編譯工作,運行你的應用程序爲:

"-Djsse.enableSNIExtension=false" 

來源的信息here

該屬性也可以在Java代碼中設置,但它必須在任何SSL操作之前設置。一旦加載了SSL庫,您可以更改該屬性,但它不會影響SNI狀態。要在運行時禁用SNI(與上述的限制),可以使用:

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

2 - 對於固定chunkedTransferMode的激活和Java堆空間錯誤。

Java堆空間錯誤:我不得不增加客戶端使用JVM內存:

做這件事在Eclipse中,轉到運行>運行配置...>選擇客戶端類>參數> VM參數:

-Xms1024m -Xmx2500m -XX:+PrintFlagsFinal 

,我用我自己的固定這個問題來源:source 1source 2source 3

關於啓用chunkedTransferMode的事實,我不需要那樣做,因爲我在jersey-client的文檔中發現,在澤西客戶端V2.13中缺省啓用chunkedTransferMode。

在我們在客戶端將這些參數傳遞給JVM結束:

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

好吧,似乎這個問題是一個非常大的文件(350Mb),並且您遇到了各種限制。因此,我建議以不同的方式解決問題。

可能的解決方案:

  1. 拆分客戶端上的文件,並通過「小」部分在那裏組裝回原來的順序服務器上傳。
  2. 流的文件到服務器:http://commons.apache.org/proper/commons-fileupload/streaming.html

我寧願2.解決方案,它可能是最容易實現的。 希望這有助於。

相關問題