public class MyServlet extends HttpServlet { /**
 * 
 */
private static final long serialVersionUID = -72959383420152113L;
public MyServlet() {
super();
} public void destroy() {
super.destroy(); 
} public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String clientIp = request.getRemoteAddr();
String servletPara = request.getQueryString();// 得请求中的servlet参数
String id = request.getParameter("id");
//String realpath = listid(id);
File file = new File("d:\\法务大管家.rar");
boolean isNewDown = true;
try {
response.setContentType("APPLICATION/OCTET-STREAM;charset=GBK"); response.setHeader("Content-Disposition",
"attachment;  filename=\"" + new String(file.getName().getBytes("gb2312"),"iso-8859-1") + "\"");

ServletOutputStream out = response.getOutputStream();
System.out.println(file.length()/1024);
ArrayList<Range> ranges = parseRange(request, response, (int) file.length());
if (ranges != null && ranges.size() > 0) {
// Partial content response. response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); if (ranges.size() == 1) { Range range = (Range) ranges.get(0);
response.addHeader("Content-Range", "bytes " + range.start
+ "-" + range.end + "/" + range.length);
long length = range.end - range.start + 1;
if (length < Integer.MAX_VALUE) {
response.setContentLength((int) length);
} else {
// Set the content-length as String to be able to use a
// long
response.setHeader("content-length", "" + length);
} continueDown(out, file, range); isNewDown = false;
} else {
System.out.println("ranges.size() > 1");
}
}else if (isNewDown) {// 新的下载
response.setContentLength((int) file.length());
newDown(out, file, clientIp, servletPara, id);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
 e.printStackTrace();
} return;
} private void continueDown(ServletOutputStream out, File file, Range range)
throws FileNotFoundException, IOException { RandomAccessFile raf = new RandomAccessFile(file, "r");
raf.seek(range.start);
byte[] bBuf = new byte[1024];
int rLen = 0;
while ((rLen = raf.read(bBuf)) > 0) {
//System.out.println("continueDown中的rLen" + rLen);
out.write(bBuf, 0, rLen);
}
} private void newDown(ServletOutputStream out, File file, String clientIp,
String servletPara, String id) {// 新的下载
Date beginTime = new Date();
double toClientTime;//总够用的时间
String saveTime=null;//转换后的时间
String isOver=null; //下载是否完成
int downloadSize = 0;

int sum = 0;
try {
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufInput = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufOut = new BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
try {
while (-1 != (bytesRead = bufInput.read(buff, 0, buff.length))) {
sum = sum + bytesRead;
bufOut.write(buff, 0, bytesRead);//出错地方
}
downloadSize=1;
} catch (IOException e) {
e.printStackTrace();
}
fileInputStream.close();
bufOut.close();
out.close();
toClientTime=(new Date().getTime()-beginTime.getTime())/1000.0; //下载一共用了多少时间

int hours=(int)toClientTime/3600;
int minute=(int)toClientTime%3600/60;
int second=(int)toClientTime%3600%60;
saveTime=hours+"时"+minute+"分"+second+"秒";
if(downloadSize!=0){
isOver="完成";
System.out.println("下载完成");
////update count down
}else{
isOver="未完成";
System.out.println("下载未完成 一共下载的大小为"+sum);
}
//IptoCountry iptocountry=new IptoCountry();
//iptocountry.insertTable(clientIp, servletPara, isOver,saveTime);
} catch (IOException e) {
e.printStackTrace();
}
} protected class Range { public long start; public long end; public long length; /**
 * Validate range.
 */
public boolean validate() {
if (end >= length)
end = length - 1;
return ((start >= 0) && (end >= 0) && (start <= end) && (length > 0));
} public void recycle() {
start = 0;
end = 0;
length = 0;
} } /**
 * Parse the range header.
 * 
 * @param request
 *            The servlet request we are processing
 * @param response
 *            The servlet response we are creating
 * @return Vector of ranges
 */
protected ArrayList<Range> parseRange(HttpServletRequest request,
HttpServletResponse response, int fileLength) throws IOException { // long fileLength = resourceAttributes.getContentLength(); if (fileLength == 0)
return null; // Retrieving the range header (if any is specified
String rangeHeader = request.getHeader("Range");
System.out.println("arraylist中的rangeheader" + rangeHeader); if (rangeHeader == null)
return null;
// bytes is the only range unit supported (and I don't see the point
// of adding new ones).
if (!rangeHeader.startsWith("bytes")) {
response.addHeader("Content-Range", "bytes */" + fileLength);
response
.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
} rangeHeader = rangeHeader.substring(6);
System.out.println("arraylist中的rangeheader2" + rangeHeader); // Vector which will contain all the ranges which are successfully
// parsed.
ArrayList<Range> result = new ArrayList<Range>();
StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ","); // Parsing the range list
while (commaTokenizer.hasMoreTokens()) {
String rangeDefinition = commaTokenizer.nextToken().trim(); Range currentRange = new Range();
currentRange.length = fileLength; int dashPos = rangeDefinition.indexOf('-'); if (dashPos == -1) {
response.addHeader("Content-Range", "bytes */" + fileLength);
response
.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
} if (dashPos == 0) { try {
long offset = Long.parseLong(rangeDefinition);
currentRange.start = fileLength + offset;
currentRange.end = fileLength - 1;
} catch (NumberFormatException e) {
response
.addHeader("Content-Range", "bytes */" + fileLength);
response
.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
} } else { try {
currentRange.start = Long.parseLong(rangeDefinition
.substring(0, dashPos));
if (dashPos < rangeDefinition.length() - 1)
currentRange.end = Long.parseLong(rangeDefinition
.substring(dashPos + 1, rangeDefinition
.length()));
else
currentRange.end = fileLength - 1;
} catch (NumberFormatException e) {
response
.addHeader("Content-Range", "bytes */" + fileLength);
response
.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
} } if (!currentRange.validate()) {
response.addHeader("Content-Range", "bytes */" + fileLength);
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return null;
} result.add(currentRange);
} return result;
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

} public void init() throws ServletException {
super.init();
}}

解决方案 »

  1.   

    google的来的结果:
    Connection reset by peer的原因: 
    经常出现的Connection reset by peer: 原因可能是多方面的,不过更常见的原因是: 
    ①:服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉; 
    ②:客户关掉了浏览器,而服务器还在给客户端发送数据; 
    ③:浏览器端按了Stop 
      

  2.   

    换个别的服务器试一下呢?可能是tomcat的配置问题。
      

  3.   

    既然实现断点续传了
    2G以下又没有问题
    那就将超过2g的文件
    每2G就自动作为一个断点呗
      

  4.   

    连接被防火樯或proxy中断,或防火墙和代理设置不当。
      

  5.   

    我看到了在续传的分支里有如下判断:                    if (length < Integer.MAX_VALUE) {
                            response.setContentLength((int) length);
                        } else {
                            // Set the content-length as String to be able to use a
                            // long
                            response.setHeader("content-length", "" + length);
                        }而在从头传的分支里却只有:            }else if (isNewDown) {// 新的下载
                    response.setContentLength((int) file.length());
                    newDown(out, file, clientIp, servletPara, id);
                }
    改成如下代码看看是否ok            }else if (isNewDown) {// 新的下载
                      if (length < Integer.MAX_VALUE) {
                        response.setContentLength((int) length);
                    } else {
                        response.setHeader("content-length", "" + length);
                    }
                    newDown(out, file, clientIp, servletPara, id);
                }
      

  6.   

    不是将文件分包,而是自己控制
    每次下载的文件最大为2G,超过
    2G的部分,就像是用户没下载完
    一样,作相同的处理,进行续传
    不就好了?而且,你也可以试试
    把你的流flush一下,貌似你把
    整个文件都写入缓存却没刷新过
    吧,你本机的内存也就2G上下吧
    呵呵