2016-05-23 139 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)