2016-05-23 137 views
0

所以我有這個代碼從磁盤(tar.gz,exe或dmg)讀取正確的安裝程序文件,並將其流式傳輸給用戶(下面的代碼)。安裝程序實際上是檔案,它可以提取和設置可以手動運行(這是特定於Windows,Mac安裝程序需要安裝,Unix安裝程序還需要提取)使用Java讀取和寫入大型二進制文件

InputStream in = null; 
    OutputStream out = null; 

    byte[] buffer = new byte[16384]; 

    try { 
     String bundle = ServletRequestUtils.getRequiredStringParameter(request, "bundle"); 

     String installerPath = constructFilePath(bundle); 
     File installer = new File(installerPath); 
     if(!installer.exists()){ 
      logger.error("Cannot read installer file"); 
      response.sendRedirect("/somewhere"); 
     }else{ 
      in = new FileInputStream(installer); 
      response.setContentType(getBundleContentType(bundle)); //application/octet-stream or application/x-gzip or application/x-apple-diskimage 
      response.setHeader("Pragma", "private"); 
      response.setHeader("Cache-Control", "private, must-revalidate"); 
      response.addHeader("Content-Disposition", "attachment;filename="+getBundleFileName(bundle)); //Setting new file name 
      out = new BufferedOutputStream(response.getOutputStream()); 

      while((in.read(buffer)) != -1) 
       out.write(buffer); 
     } 
    } catch (Exception e) { 
     logger.error("Exception downloading installer file, reason: " + e); 
     response.sendRedirect("/somewhere"); 
    } finally { 
     if(in != null){ 
      in.close(); 
     } 
     if(out != null){ 
      out.flush(); 
      out.close(); 
     } 
    } 

    return null; 

我會好好以Windows(.exe)安裝程序爲例。以前,當我將代碼重定向到http:///somepath/installer.exe進行下載時,該文件將被下載,並且我可以使用7zip將其解壓縮,但是現在,當我嘗試提取它時與7zip,我得到:

Cannot open file as archive. 

但是,我能夠雙擊.exe併成功地進行安裝。我也可以使用winRAR解壓縮它。

Unix安裝程序發生了同樣的情況。當我將它下載到一臺Unix機器,並嘗試提取它(右鍵點擊「提取這裏」)我得到這個錯誤:

gzip: stdin: decompression OK, trailing garbage ignored 
/bin/gtar: Child returned status 2 
/bin/gtar: Error is not recoverable: exiting now 

但是,我能夠與「方舟」打開它,正確提取其內容。

我還應該指出,下載後文件的字節不匹配(下載文件與文件系統上的文件應該相同)。

我錯過了什麼嗎?

回答

2

你可以嘗試寫正是你讀同一數據:

while ((read = in.read(buffer)) != -1) { 
    out.write(buffer, 0, read); 
} 
0

這是因爲你被寫入整個緩衝區。

想象一下這個文件是16385字節。

第一個in.read(buffer)將填滿整個緩衝區並返回16384.然後您將寫入整個緩衝區。第二次,它會讀取一個字節,然後再次寫入整個緩衝區。

有人打我,但我要補充一點,你可以使用IOUtils做到這一點...

http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html

例如IOUtils.copy(in, out)