Java 下载超过2GB的文件

Java 下载超过2GB的文件

I discovered a few days back an issue with our product on HTTP downloads > 2GB.

 It appears to be a simple overflow on the HttpServletResponse.setContentLength method.

You can probably excuse the API designers circa 1997 assuming a 32-bit signed Integer with

max value 231-1 (2147483647 bytes) would be sufficient.  The Gigabit ethernet standard did not

come for another year (1998)!

Here is the exception seen when you provide a long value greater than 2147483647 bytes to

the setContentLength(int) method:

java.net.ProtocolException: Exceeded stated content-length of: '-XXXX' bytes 
        at weblogic.servlet.internal.ServletOutputStreamImpl.checkCL(ServletOutputStreamImpl.java:200)

Below is a sample download servlet with workaround for the 2gb limitation.

 It has been tested on Firefox 3.6 against WebLogic Server 10.3.6 with a 2.2GB download and worked perfectly.


import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream;

import javax.servlet.ServletContext; 
import javax.servlet.ServletException; 
import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse;


public class DownloadServlet 
  extends HttpServlet 
{ 
  @SuppressWarnings("compatibility:1533750721037291976") 
  private static final long serialVersionUID = 1L;

  protected void doGet(HttpServletRequest request, 
    HttpServletResponse response) 
    throws ServletException, IOException 
  { 
    doPost(request, response); 
  }

  protected void doPost(HttpServletRequest request, 
    HttpServletResponse response) 
    throws ServletException, IOException 
  { 
    // if no file parameter specified, download hosts file 
    String file = request.getParameter("file"); 
    file = (file == null || file.length() == 0) ? "/etc/hosts" : file;

    File fileObj = new File(file); 
    if ((!fileObj.exists()) || (!fileObj.isFile()) || (!fileObj.canRead())) 
    { 
      throw new IOException("'file' '" + file + "' cannot be read."); 
    }

    ServletContext context = getServletConfig().getServletContext();

    String mimetype = context.getMimeType(file); 
    response.setContentType(mimetype == null ? "application/octet-stream" : 
        mimetype);

    long length = fileObj.length(); 
    if (length <= Integer.MAX_VALUE) 
    { 
      response.setContentLength((int)length); 
    } 
    else 
    { 
      response.addHeader("Content-Length", Long.toString(length)); 
    }

    response.setHeader("Content-Disposition", 
        "attachment; filename=\"" + fileObj.getName() + "\"");

    ServletOutputStream out = response.getOutputStream(); 
    InputStream in = null; 
    byte[] buffer = new byte[32768]; 
    try 
    { 
      in = new FileInputStream(fileObj);

      int bytesRead; 
      while ((bytesRead = in.read(buffer)) >= 0) 
      { 
        out.write(buffer, 0, bytesRead); 
      } 
    } 
    finally 
    { 
      if (in != null) 
      { 
        in.close(); 
      } 
    } 
  } 
} 


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值