Javaweb 实现断点续传
1.方法
代码
package cn.test.servlet;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public classdown extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
ServletContextservletContext=getServletContext();//获得servletContext对象
request.setCharacterEncoding("utf-8");//设置编码格式
Stringurl = "http://dlsw.baidu.com/sw-search-sp/soft/3a/12350/QQ5.3.10716.0.1397783519.exe";//获得下载地址
StringdownFile = "C:\\Users\\Administrator\\Desktop\\QQ.exe";//获得保存地址
LongnetFileLenght = getNetFileSize(url);//获得网络数据字符流长度
LonglocalFileLenght = getLocalFileSize(downFile);//获得已下载本地数据字符流长度
request.setAttribute("process",netFileLenght);
servletContext.getRequestDispatcher("/MyJsp.jsp").forward(request,response);
if (localFileLenght >=netFileLenght) {
System.out.println("已下载完成");
return;
}
System.out.println("netFileLenght : "+ netFileLenght+" localFileLenght : " + localFileLenght);
final HttpClient httpClient =newDefaultHttpClient();
httpClient.getParams().setIntParameter("http.socket.timeout",5000);
final HttpGet httpGet =new HttpGet(url);
httpGet.addHeader("Range","bytes="+ localFileLenght +"-");
final HttpResponse response1= httpClient.execute(httpGet);
final int code =response1.getStatusLine().getStatusCode();
final HttpEntity entity =response1.getEntity();
System.out.println(code);
if (entity !=null && code <400) {
Filefile = newFile(downFile);
RandomAccessFilerandomAccessFile = newRandomAccessFile(file,"rw");
randomAccessFile.seek(localFileLenght);
InputStreaminputStream = entity.getContent();
int b = 0;
final byte buffer[] = new byte[1024];
while ((b = inputStream.read(buffer)) != -1) {
randomAccessFile.write(buffer, 0, b);
}
randomAccessFile.close();
inputStream.close();
httpClient.getConnectionManager().shutdown();
System.out.println("下载完成");
}
}
public static LonggetLocalFileSize(String fileName) {//获取本地保存地址的字符流长度
Filefile = newFile(fileName);
return file.length();
}
public static LonggetNetFileSize(String url) {//获取网络下载地址的字符流长度
Longcount = -1L;
final HttpClient httpClient =newDefaultHttpClient();
httpClient.getParams().setIntParameter("http.socket.timeout",5000);
final HttpGet httpGet =new HttpGet(url);
HttpResponseresponse = null;
try {
response= httpClient.execute(httpGet);
final int code=response.getStatusLine().getStatusCode();
final HttpEntity entity=response.getEntity();
if (entity !=null && code == 200){
count= entity.getContentLength();
}
}
catch(ClientProtocolException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally{
httpClient.getConnectionManager().shutdown();
}
return count;
}
public voiddoPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
doGet(request, response);
}
}
getNetFileSize这个方法是在网上找的
大概流程是index.jsp通过超文本连接调用down.java这个servlet,servlet获取下载地址以及保持位置,通过getLocalFileSize和getNetFileSize两个方法获得本地保存位置的文件的字节数和远程资源文件的字节数,进行判断,如果小于后者,则在前者字节数基础上继续下载,如果相等则下载完毕。转发给MyJsp.jsp.
测试图片:
第一行数据为初次下载时
远程资源为58325176
检测本地文件资源为0
即前尚未下载。
第二行数据为关闭浏览器后,重新打开下载
检测到远程资源为58325176
检测本地文件资源为8779765
小于第一个数
则继续下载
第三行和第二行一样
2.方法
浏览器第一次下载时会先用一个变量
记录下载数据的字节数通过cookie保存在客户电脑中,生命周期较长
下次打开时,读取这个变量,然后在变量加1的位置继续下载
其实两者差不多
关于下载进度条
1.html5+javascript
代码
<!DOCTYPE html>
<html>
<head>
<title>down</title>
<script type="text/javascript">
var currProgress = 0;
var done = false;
var total = 100;
function startProgress() {
var prBar =document.getElementById("prog");
var startButt =document.getElementById("startBtn");
var val =document.getElementById("numValue");
startButt.disabled=true;
prBar.value = currProgress;
val.innerHTML =Math.round((currProgress/total)*100)+"%";
currProgress++;
if(currProgress>100) done=true;
if(!done)
setTimeout("startProgress()", 100);
else
{
document.getElementById("startBtn").disabled = false;
done = false;
currProgress = 0;
}
}
</script>
</head>
<body>
<p>Task progress:</p>
<progress id="prog"value="0" max="100"></progress>
<input id="startBtn"type="button" value="start" onclick="startProgress()"/>
<divid="numValue">0%</div>
</body>
</html>
但是标签progress在我的IE浏览器上无法使用
只会显示下载百分比
现在只有火狐 谷歌 opera 上支持
2.javacript
<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>进度条</title>
<style type="text/css">
body{
text-align:center;
}
.graph{
width:450px;
border:1px solid #F8B3D0;
height:25px;
}
#bar{
display:block;
background:#FFE7F4;
float:left;
height:100%;
text-align:center;
}
#barNum{
position:absolute;
}
</style>
<scripttype="text/javascript">
function $(obj){
return document.getElementById(obj);
}
function go(){
$("bar").style.width =parseInt($("bar").style.width) + 1 + "%";
$("bar").innerHTML =$("bar").style.width;
if($("bar").style.width =="100%"){
window.clearInterval(bar);
}
}
var bar =window.setInterval("go()",50);
window.onload = function(){
bar;
}
</script>
</head>
<body>
<div class="graph">
<strong id="bar"style="width:1%;"></strong>
</div>
</body>
</html>
这个代码没看懂
下载进程问题
servlet将正下载数据字节数以及总数据数通过
resquest域传给前台
并不断刷新进度显示页面,
需要多线程技术
因为servlet是处理请求与响应的
如果下载时间很长,网页不可能一直在等待处理结果
所以需要另外一个线程处理下载,并不断返回已下载数据的字节数
可以通过Ajax让进度显示页面不断获取此数据,并显示
但是servlet中不能使用多线程(servlet本身就是多线程,这样会使线程安全性很差)
需要使用javabean来创建线程(不知道对不对)
然后在servlet中调用javabean对象实现多线程