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
    评论
commons-fileupload-1.2.1实现文件上传 需导入commons-fileupload-1.2.1.jar和 commons-io-1.3.2.jar upload2.jsp <%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>文件上传</title> </head> <body> <form action="FileUploadServlet" method="post" enctype="multipart/form-data"> <input type="file" size="30" name="file01" /> <br /> <input type="file" size="30" name="file02" /> <br /> <input name="up" type="submit" value="上传" /> </form> </body> FileUploadServlet.java import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class FileUploadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final long MAX_SIZE = 300 * 1024 * 1024;// 设置上传文件最大值 // 允许上传的文件格式的列表 final String[] allowedExt = new String[] { "jpg", "jpeg", "gif", "txt", "doc", "mp3", "wma", "m4a", "rar", "zip" }; response.setContentType("text/html"); // 设置字符编码为UTF-8, 统一编码,处理出现乱码问题 response.setCharacterEncoding("UTF-8"); // 实例化一个硬盘文件工厂,用来配置上传组件ServletFileUpload DiskFileItemFactory dfif = new DiskFileItemFactory(); dfif.setSizeThreshold(4096);// 设置上传文件时用于临时存放文件的内存大小,这里是4K.多于的部分将临时存在硬盘 dfif.setRepository(new File(request.getRealPath("/") + "ImagesUploadTemp"));// 设置存放临时文件的目录,web根目录下的ImagesUploadTemp目录 // 用以上工厂实例化上传组件 ServletFileUpload sfu = new ServletFileUpload(dfif); // 设置最大上传大小 sfu.setSizeMax(MAX_SIZE); PrintWriter out = response.getWriter(); // 从request得到所有上传域的列表 List fileList = null; try { fileList = sfu.parseRequest(request); } catch (FileUploadException e) {// 处理文件尺寸过大异常 if (e instanceof SizeLimitExceededException) { out.println("文件尺寸超过规定大小:" + MAX_SIZE + "字节<p />"); out .println("<a href=\"upload2.jsp\" target=\"_top\">返回</a>"); return; } e.printStackTrace(); } // 没有文件上传 if (fileList == null || fileList.size() == 0) { out.println("请选择上传文件<p />"); out.println("<a href=\"upload2.jsp\" target=\"_top\">返回</a>"); return; } // 得到所有上传的文件 Iterator fileItr = fileList.iterator(); // 循环处理所有文件 while (fileItr.hasNext()) { FileItem fileItem = null; String path = null; long size = 0; // 得到当前文件 fileItem = (FileItem) fileItr.next(); // 忽略简单form字段而不是上传域的文件域(<input type="text" />等) if (fileItem == null || fileItem.isFormField()) { continue; } // 得到文件的完整路径 path = fileItem.getName(); // 得到文件的大小 size = fileItem.getSize(); if ("".equals(path) || size == 0) { out.println("请选择上传文件<p />"); out .println("<a href=\"upload2.jsp\" target=\"_top\">返回</a>"); return; } // 得到去除路径的文件名 String t_name = path.substring(path.lastIndexOf("\\") + 1); System.out.println(t_name); // 得到文件的扩展名(无扩展名时将得到全名) String t_ext = t_name.substring(t_name.lastIndexOf(".") + 1); // 拒绝接受规定文件格式之外的文件类型 int allowFlag = 0; int allowedExtCount = allowedExt.length; for (; allowFlag < allowedExtCount; allowFlag++) { if (allowedExt[allowFlag].equals(t_ext)) break; } if (allowFlag == allowedExtCount) { out.println("请上传以下类型的文件<p />"); for (allowFlag = 0; allowFlag < allowedExtCount; allowFlag++) out.println("*." + allowedExt[allowFlag] + " "); out .println("<p /><a href=\"upload2.jsp\" target=\"_top\">返回</a>"); return; } long now = System.currentTimeMillis(); // 根据系统时间生成上传后保存的文件名 String prefix = String.valueOf(now); // 保存的最终文件完整路径,保存在web根目录下的ImagesUploaded目录下 String u_name = request.getRealPath("/") + "ImagesUploaded/" + prefix + "." + t_ext; //String filename = prefix + "." + t_ext; //根据原文件名保存文件 String filename=t_name; try { // 保存文件到C:\\upload目录下 fileItem.write(new File("D:\\upload\\" + filename)); System.out.println(filename); out.println("文件上传成功. 已保存为: " + t_name + " 文件大小: " + size + "字节<p />"); out .println("<a href=\"upload2.jsp\" target=\"_top\">继续上传</a>"); } catch (Exception e) { e.printStackTrace(); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } } </html>
PilotEdit是中国公司开发的功能强大的文件编辑器。PilotEdit破解版包含了文本编辑、HEX编辑、FTP上传下载文件目录比较、基于正则表达式的查找和替换以及加密解密等诸多功能为一体的软件。软件界面友好,功能强大,是一款非常不错的软件。   1、PilotEdit支持超过400G的文件   >编辑超过400GB(400亿行)的文件   >上传/下载超过4G的FTP文件   >加密/解密超过4G的文件   >比较超过4G的文件   2、全面支持UNICODE文件和DOS/UNIX文件   >快速改变多个文件的编码   >在不同编码的文件中拷贝文字时自动调整文字编码   3、自定义的文件类型和关键字高亮显示   >支持超过20种文件类型   >支持自定义文件类型   >对不同的文件类型定义不同的TAB和缩进   比如,您可以定义当用户按TAB键时,在C/C++中输入TAB键,而在Java文件中输入四个空格   4、十六进制编辑模式   >在十六进制编辑模式中可以很方便地插入,修改,删除,拷贝,粘贴   >十六进制编辑模式查找和替换   >当从十六进制编辑模式切换回文本模式时自动检测文件类型   >在十六进制编辑模式和文本模式中无限的undo/redo   5、列模式   >键盘输入的字符将被插入到列模式中所有选中的行   >如果粘贴一行文字,这行文字将被插入到列模式中所有选中的行   >如果粘贴多行文字,这些文字将被逐行被插入到列模式中选中的行   6、无限的undo/redo   >在十六进制编辑模式和文本模式切换后仍然可以无限次地undo/redo   7、回行显示   >即便在编辑一个几百MB的文件时,切换到回行显示仍然非常迅速   8、编辑FTP文件   >打开和保存FTP文件   >删除多个FTP文件和目录   >上传/下载多个FTP文件和目录   9、基于多行的查找和替换   >查找/替换多行文本   >用正则表达式查找/替换多行文本   10、文件比较和合并   >比较两个基本点目录   >比较合并两个文件   >在文件比较窗口中直接编辑文件   >当文件内容改变时文件比较窗口自动更新比较结果   >在文件比较窗口中查找/替换   >查找上一个/下一个不同的文本块   >将所有相同/不同的行拷贝到剪贴板。通过这个功能,我们可以很方便地找出第一个文件中存在而第二个文件中不存在的行   11、自定义字符串表   >单击即可添加一个自定义的字符串   >在所选文本的前后分别添加自定义的字符串   12、正则表达式   >用正则表达式查找/替换多行文本   13、脚本文件   >可以把常用的正则表达式定义在脚本中,直接运行脚本即可替换文字   14、256位 AES加密/解密   >用PilotEdit直接透明地编辑一个加密的文件   >加密/解密多个文件和目录   >加密/解密超过4G的文件   15、文件组   >双击文件组可以快速打开多个文件   16、在多个目录中查找/替换   >支持多行的查找/替换   17、排序   >按升序/降序排序   >按文本或数字排序   >按一列数据排序   >按正则表达式排序   18、查找/删除重复的行   >在打开的文件中查找/删除重复的行   >按文本或数字比较   >按一列数据比较   >按正则表达式比较   19、收集字符串   >将匹配正则表达式字符串拷贝到的剪贴板。比如,我们可以把一个文件中所有的Email地址拷贝到剪贴板。   20、将打开的文件用原目录结构另存为新文件   >同时拷贝选中的文件和目录结构   21、编辑SFTP文件   >打开和保存SFTP文件   >删除多个SFTP文件和目录   >上传/下载多个SFTP文件和目录
### 回答1: public class SplitFile { public static void main(String[] args) { File file = new File("inputFile.txt"); int partCounter = 1; int sizeOfFiles = 1024 * 1024 * 2;// 2MB byte[] buffer = new byte[sizeOfFiles]; try (FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis)) { int bytesAmount = 0; while ((bytesAmount = bis.read(buffer)) > 0) { //write each chunk of data into separate file with different number in name String filePartName = String.format("%s.%03d", file.getName(), partCounter++); File newFile = new File(file.getParent(), filePartName); try (FileOutputStream out = new FileOutputStream(newFile)) { out.write(buffer, 0, bytesAmount); } } } catch (IOException e) { e.printStackTrace(); } } } ### 回答2: 可以使用Java的IO流和文件操作来实现文件拆分。下面是使用Java代码将文件大小超过2G文件进行拆分的示例: ```java import java.io.*; public class FileSplitter { private static final long MAX_FILE_SIZE = 2L * 1024 * 1024 * 1024; // 2G public static void splitFile(File inputFile) throws IOException { long fileSize = inputFile.length(); if (fileSize <= MAX_FILE_SIZE) { System.out.println("文件大小低于2G,无需拆分。"); return; } FileInputStream fileInputStream = new FileInputStream(inputFile); BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); byte[] buffer = new byte[1024]; int bytesRead; int partNumber = 1; while ((bytesRead = bufferedInputStream.read(buffer)) != -1) { String fileName = inputFile.getName() + "." + partNumber; File outputFile = new File(fileName); FileOutputStream fileOutputStream = new FileOutputStream(outputFile); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); bufferedOutputStream.write(buffer, 0, bytesRead); bufferedOutputStream.flush(); bufferedOutputStream.close(); partNumber++; } bufferedInputStream.close(); fileInputStream.close(); System.out.println("文件拆分完成。"); } public static void main(String[] args) { File inputFile = new File("path/to/inputFile.txt"); // 替换成实际的文件路径 try { splitFile(inputFile); } catch (IOException e) { e.printStackTrace(); } } } ``` 以上代码首先会判断输入文件的大小,如果文件大小低于或等于2G,则无需进行拆分。否则,会逐部分读取文件内容,并将每部分内容写入单独的输出文件中。输出文件的命名规则为原始文件名加上拆分的部分编号。拆分后的部分文件将与原始文件在同一目录下。 注意:以上代码仅作为示例,实际应用中还需要考虑异常处理、文件路径验证、文件名冲突等问题。 ### 回答3: 编写一段Java代码,用于将超过2G大小的文件进行拆分。 ```java import java.io.*; public class FileSplitter { public static void main(String[] args) { String sourceFilePath = "path_to_source_file"; // 源文件路径 String outputDirectory = "path_to_output_directory"; // 拆分后输出的目录 splitFile(sourceFilePath, outputDirectory); } public static void splitFile(String sourceFilePath, String outputDirectory) { try { File sourceFile = new File(sourceFilePath); long fileSize = sourceFile.length(); int partSize = 1024 * 1024 * 1024; // 1 GB int partCounter = 0; byte[] buffer = new byte[partSize]; try (InputStream inputStream = new BufferedInputStream(new FileInputStream(sourceFile))) { String fileName = sourceFile.getName(); int bytesRead; while ((bytesRead = inputStream.read(buffer)) > 0) { String outputFileName = String.format("%s/%s.%03d", outputDirectory, fileName, partCounter); try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFileName))) { outputStream.write(buffer, 0, bytesRead); } catch (IOException e) { e.printStackTrace(); } partCounter++; } } catch (IOException e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } } ``` 上述代码首先定义了一个`splitFile`方法,该方法接收源文件路径和拆分后输出的目录作为参数。首先获取源文件的大小,然后定义一个1GB大小的缓冲区。 在主方法中,你需要设置源文件路径和拆分后输出的目录,然后调用`splitFile`方法。 `splitFile`方法首先创建一个源文件对象,并获取文件的大小。然后设置拆分后的每个部分的大小为1GB。使用一个循环,每次从源文件中读取1GB的内容,并将内容写入到一个新的文件中。新文件的命名规则为`源文件名.部分编号`,例如`sourceFile.001`。 通过以上代码,你可以将超过2G大小的文件拆分成多个1GB的文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值