关闭

Java 下载超过2GB的文件

603人阅读 评论(0) 收藏 举报
分类:

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(); 
      } 
    } 
  } 
} 


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:142875次
    • 积分:1728
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:140篇
    • 译文:0篇
    • 评论:17条
    文章分类
    最新评论