断点续传(客户端和服务器端实现)
来源:互联网 发布:中科大算法导论 编辑:程序博客网 时间:2024/06/06 05:49
断点续传(客户端和服务器端实现)
2013-09-05 15:51 4360人阅读 评论(4)收藏举报
本文章已收录于:
分类:
作者同类文章X
版权声明:本文为博主原创文章,未经博主允许不得转载。
所谓断点续传,也就是要从文件已经下载的地方开始继续下载。
客户端从服务器端下载文件,服务器端支持分段下载,这样子,还可以进行多线程分段下载(在此就不提供了)。
服务器端的支持:
- public class DownloadServlet extends HttpServlet {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- // TODO Auto-generated method stub
- OutputStream os = null;
- FileInputStream is = null;
- try {
- File f = new File(
- "/home/agilemobi/Desktop/laolian_client_for_android_v1.0.apk");
- is = new FileInputStream(f);
- long fileSize = f.length();
- resp.setHeader("Accept-Ranges", "bytes");
- // resp.setHeader("Content-Length", fileSize + "");
- String range = req.getHeader("Range");
- int status = HttpServletResponse.SC_OK; // 返回的状态码,默认200,首次下载
- // 如果range下载区域为空,则首次下载,
- if(range == null){
- range = "bytes=0-";
- } else {
- // 通过下载区域下载,使用206状态码支持断点续传
- status = HttpServletResponse.SC_PARTIAL_CONTENT;
- }
- long start = 0, end = 0;
- if (null != range && range.startsWith("bytes=")) {
- String[] values = range.split("=")[1].split("-");
- start = Integer.parseInt(values[0]);
- // 如果服务器端没有设置end结尾,默认取下载全部
- if(values.length == 1){
- end = fileSize;
- } else {
- end = Integer.parseInt(values[1]);
- }
- }
- // 此次数据响应大小
- long responseSize = 0;
- if (end != 0 && end > start) {
- responseSize = end - start + 1;
- // 返回当前连接下载的数据大小,也就是此次数据传输大小
- resp.addHeader("Content-Length", "" + (responseSize));
- } else {
- responseSize = Integer.MAX_VALUE;
- }
- byte[] buffer = new byte[4096];
- // 设置响应状态码
- resp.setStatus(status);
- if(status == HttpServletResponse.SC_PARTIAL_CONTENT){
- // 设置断点续传的Content-Range传输字节和总字节
- resp.addHeader("Content-Range", "bytes " + start + "-" + (fileSize - 1) + "/" + fileSize);
- }
- // 设置响应客户端内容类型
- resp.setContentType("application/x-download");
- // 设置响应客户端头
- resp.addHeader("Content-Disposition", "attachment;filename=laolian_client_for_android_v1.0.apk");
- // 当前需要下载文件的大小
- int needSize = (int)responseSize;
- if(start != 0){
- // 跳已经传输过的字节
- is.skip(start);
- }
- os = resp.getOutputStream();
- while (needSize > 0) {
- int len = is.read(buffer);
- if (needSize < buffer.length) {
- os.write(buffer, 0, needSize);
- } else {
- os.write(buffer, 0, len);
- // 如果读取文件大小小于缓冲字节大小,表示已写入完,直接跳出
- if (len < buffer.length) {
- break;
- }
- }
- // 不断更新当前可下载文件大小
- needSize -= buffer.length;
- }
- } catch (IOException e) {
- e.printStackTrace();
- return;
- } finally {
- if (is != null)
- is.close();
- if (os != null)
- os.close();
- }
- }
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- // TODO Auto-generated method stub
- super.doPost(req, resp);
- }
- }
客户端:
- public class TestConn {
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- // TODO Auto-generated method stub
- String urlstr = "http://localhost:8090/mydownload/DownloadServlet";
- URL url = new URL(urlstr);
- HttpURLConnection connection = (HttpURLConnection) url
- .openConnection();
- connection.setConnectTimeout(5000);
- connection.setRequestMethod("GET");
- // connection.setRequestProperty("Accept-Encoding", "identity");
- connection.connect();
- int fileSize = connection.getContentLength();
- System.out.println(connection.getResponseCode());
- System.out.println(fileSize);
- connection.disconnect();
- download(0, 0, 20000, urlstr);
- }
- private static void download(int startPos, int compeleteSize, int endPos, String urlstr){
- HttpURLConnection connection = null;
- RandomAccessFile randomAccessFile = null;
- InputStream is = null;
- try {
- URL url = new URL(urlstr);
- connection = (HttpURLConnection) url.openConnection();
- connection.setConnectTimeout(5000);
- connection.setRequestMethod("GET");
- // 设置范围,格式为Range:bytes x-y;
- connection.setRequestProperty("Range", "bytes="
- + (startPos + compeleteSize) + "-" + endPos);
- randomAccessFile = new RandomAccessFile("/home/agilemobi/Desktop/1.apk", "rwd");
- randomAccessFile.seek(startPos + compeleteSize);
- // 将要下载的文件写到保存在保存路径下的文件中
- is = connection.getInputStream();
- byte[] buffer = new byte[4096];
- int length = -1;
- while ((length = is.read(buffer)) != -1) {
- randomAccessFile.write(buffer, 0, length);
- compeleteSize += length;
- System.out.println("compeleteSize:" + compeleteSize);
- }
- System.out.println("OVER:" + compeleteSize);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if(is != null)
- is.close();
- if(randomAccessFile != null)
- randomAccessFile.close();
- if(connection != null)
- connection.disconnect();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
关键点:
客户端
1.
- connection.setRequestProperty("Range", "bytes="
- + (startPos + compeleteSize) + "-" + endPos);
- RandomAccessFile的使用
服务器端
1.对HTTP头Range信息的解析。
2.InputStream的skip()跳过多少字节流。
3.状态的设置。
4.Content-Length的设置,否则客户端getContentLength()返回为-1。
- resp.addHeader("Content-Length", "" + (responseSize));
- 顶
- 1
- 踩
- 0
- 上一篇Android Service 的重启
- 下一篇金额转大写
我的同类文章
http://blog.csdn.net
- •金额转大写2015-12-23
- •jsp 页面静态化 java.net.MalformedURLException: no protocol: index.jsp和java.net.MalformedURLException: unknown protocol: d2010-04-18
- •将.class文件打包成jar文件2009-09-04
- •android表单上传出现java.lang.NoClassDefFoundError2012-04-24
- •(利用键值对)java中打印集合中字符出现次数2009-10-21
参考知识库
- 猜你在找
- 全网服务器数据备份解决方案案例实践
- Nginx服务器入门
- EasyDarwin开源流媒体服务器:编译、配置、部署
- 2016软考网络工程师信道数据传输速率与码元速率强化训练教程
- 征服JavaScript高级程序设计与应用实例视频课程
- FTP客户端实现断点续传
- 使用orgapachecommonsnetftp包开发FTP客户端实现进度汇报实现断点续传中文支持
- 使用orgapachecommonsnetftp包开发FTP客户端实现进度汇报实现断点续传中文支持
- 使用orgapachecommonsnetftp包开发FTP客户端实现进度汇报实现断点续传中文支持
- 使用orgapachecommonsnetftp包开发FTP客户端实现进度汇报实现断点续传中文支持
更多资料请参考:
0 0
- 断点续传(客户端和服务器端实现)
- 断点续传(客户端和服务器端实现)
- 服务器端和android客户端通信 服务器端实现
- 用Socket实现客户端和服务器端通信(完整版)
- 使用 Velocity 实现客户端和服务器端模板(三)
- svn(服务器端和客户端)
- FTP客户端实现断点续传
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- 使用 Velocity 实现客户端和服务器端模板
- axis2 webservice 服务器端和客户端实现例子。
- 实现服务器端和客户端的Socket通信
- Velocity 实现客户端和服务器端模板
- 常用框架
- 索引之LinearLayout侧边栏+listview实现
- ArcGIS 10.5 Prerelease is now available
- 如何将jar包加入到Maven本地仓库
- 表单中的方法
- 断点续传(客户端和服务器端实现)
- SQL那些事儿(七)--oracle表空间、用户查看基本语句
- 使用Android ButterKnife Zelezny的正确姿势
- Redis 结合Yii2总结
- 浅谈JavaScript中创建对象的几种方式
- windows 下环境变量 path 详解
- Java是纯面向对象的语言吗?
- Error:(1, 0) Plugin with id 'com.android.application' not found的解决方法
- ListView分页
所以responseSize = end - start ,不是 end - start+1,不然下载的文件与原文件作MD5比较或直接输出大小会发现已经不是同个文件
所以responseSize = end - start ,不是 end - start+1,不然下载的文件与原文件作MD5比较或直接输出大小会发现已经不是同个文件