Java网络编程从入门到精通(24):实现HTTP断点续传下载工具(附源代码)
在前面的文章曾讨论了HTTP消息头的三个和断点继传有关的字段。一个是请求消息的字段Range,另两个是响应消息字段Accept-Ranges和Content-Range。其中Accept-Ranges用来断定Web服务器是否支持断点继传功能。在这里为了演示如何实现断点继传功能,假设Web服务器支持这个功能;因此,我们只使用Range和Content-Range来完成一个断点继传工具的开发。
http://www.ishare.cc/d/1174292-2/156.jpg d:\ok2.jpg 12345
http://www.ishare.cc/d/1174277-2/147.jpg d:\ok3.jpg 3456
- 要下载的Web资源的URL。
- 要保存的本地文件名。
- 下载的缓冲区大小(单位是字节)。
public interface DownloadEvent
{
void percent(long n); // 下载进度
void state(String s); // 连接过程中的状态切换
void viewHttpHeaders(String s); // 枚举每一个响应消息字段
}
002
003 import java.net.*;
004 import java.io.*;
005 import java.util.*;
006
007 public class HttpDownload
008 {
009 private HashMap httpHeaders = new HashMap();
010 private String stateCode;
011
012 // generateHttpRequest方法
013
014 /* ananlyzeHttpHeader方法
015 *
016 * addHeaderToMap方法
017 *
018 * analyzeFirstLine方法
019 */
020
021 // getFileSize方法
022
023 // download方法
024
025 /* getHeader方法
026 *
027 * getIntHeader方法
028 */
029 }
002 String path, long startPos) throws IOException
003 {
004 OutputStreamWriter writer = new OutputStreamWriter(out);
005 writer.write("GET " + path + " HTTP/1.1\r\n");
006 writer.write("Host: " + host + "\r\n");
007 writer.write("Accept: */*\r\n");
008 writer.write("User-Agent: My First Http Download\r\n");
009 if (startPos > 0) // 如果是断点续传,加入Range字段
010 writer.write("Range: bytes=" + String.valueOf(startPos) + "-\r\n");
011 writer.write("Connection: close\r\n\r\n");
012 writer.flush();
013 }
002 throws Exception
003 {
004 String s = "";
005 byte b = -1;
006 while (true)
007 {
008 b = (byte) inputStream.read();
009 if (b == '\r')
010 {
011 b = (byte) inputStream.read();
012 if (b == '\n')
013 {
014 if (s.equals(""))
015 break;
016 de.viewHttpHeaders(s);
017 addHeaderToMap(s);
018 s = "";
019 }
020 }
021 else
022 s += (char) b;
023 }
024 }
025
026 private void analyzeFirstLine(String s)
027 {
028 String[] ss = s.split("[ ]+");
029 if (ss.length > 1)
030 stateCode = ss[1];
031 }
032 private void addHeaderToMap(String s)
033 {
034 int index = s.indexOf(":");
035 if (index > 0)
036 httpHeaders.put(s.substring(0, index), s.substring(index + 1) .trim());
037 else
038 analyzeFirstLine(s);
039 }
002 {
003 return (String) httpHeaders.get(header);
004 }
005 private int getIntHeader(String header)
006 {
007 return Integer.parseInt(getHeader(header));
008 }
002 {
003 long length = -1;
004 try
005 {
006 length = getIntHeader("Content-Length");
007 String[] ss = getHeader("Content-Range").split("[/]");
008 if (ss.length > 1)
009 length = Integer.parseInt(ss[1]);
010 else
011 length = -1;
012 }
013 catch (Exception e)
014 {
015 }
016 return length;
017 }
002 int cacheSize) throws Exception
003 {
004 File file = new File(localFN);
005 long finishedSize = 0;
006 long fileSize = 0; // localFN所指的文件的实际大小
007 FileOutputStream fileOut = new FileOutputStream(localFN, true);
008 URL myUrl = new URL(url);
009 Socket socket = new Socket();
010 byte[] buffer = new byte[cacheSize]; // 下载数据的缓冲
011
012 if (file.exists())
013 finishedSize = file.length();
014
015 // 得到要下载的Web资源的端口号,未提供,默认是80
016 int port = (myUrl.getPort() == -1) ? 80 : myUrl.getPort();
017 de.state("正在连接" + myUrl.getHost() + ":" + String.valueOf(port));
018 socket.connect(new InetSocketAddress(myUrl.getHost(), port), 20000);
019 de.state("连接成功!");
020
021 // 产生HTTP请求消息
022 generateHttpRequest(socket.getOutputStream(), myUrl.getHost(), myUrl
023 .getPath(), finishedSize);
024
025 InputStream inputStream = socket.getInputStream();
026 // 分析HTTP响应消息头
027 analyzeHttpHeader(inputStream, de);
028 fileSize = getFileSize(); // 得到下载文件的实际大小
029 if (finishedSize >= fileSize)
030 return;
031 else
032 {
033 if (finishedSize > 0 && stateCode.equals("200"))
034 return;
035 }
036 if (stateCode.charAt(0) != '2')
037 throw new Exception("不支持的响应码");
038 int n = 0;
039 long m = finishedSize;
040 while ((n = inputStream.read(buffer)) != -1)
041 {
042 fileOut.write(buffer, 0, n);
043 m += n;
044 if (fileSize != -1)
045 {
046 de.percent(m * 100 / fileSize);
047 }
048 }
049 fileOut.close();
050 socket.close();
051 }
002
003 import java.io.*;
004
005 class NewProgress implements DownloadEvent
006 {
007 private long oldPercent = -1;
008 public void percent(long n)
009 {
010 if (n > oldPercent)
011 {
012 System.out.print("[" + String.valueOf(n) + "%]");
013 oldPercent = n;
014 }
015 }
016 public void state(String s)
017 {
018 System.out.println(s);
019 }
020 public void viewHttpHeaders(String s)
021 {
022 System.out.println(s);
023 }
024 }
025
026 public class Main
027 {
028 public static void main(String[] args) throws Exception
029 {
030
031 DownloadEvent progress = new NewProgress();
032 if (args.length < 1)
033 {
034 System.out.println("用法:java class 下载文件名");
035 return;
036 }
037 FileInputStream fis = new FileInputStream(args[0]);
038 BufferedReader fileReader = new BufferedReader(new InputStreamReader(
039 fis));
040 String s = "";
041 String[] ss;
042 while ((s = fileReader.readLine()) != null)
043 {
044 try
045 {
046 ss = s.split("[ ]+");
047 if (ss.length > 2)
048 {
049 System.out.println("\r\n---------------------------");
050 System.out.println("正在下载:" + ss[0]);
051 System.out.println("文件保存位置:" + ss[1]);
052 System.out.println("下载缓冲区大小:" + ss[2]);
053 System.out.println("---------------------------");
054 HttpDownload httpDownload = new HttpDownload();
055 httpDownload.download(new NewProgress(), ss[0], ss[1],
056 Integer.parseInt(ss[2]));
057 }
058 }
059 catch (Exception e)
060 {
061 System.out.println(e.getMessage());
062 }
063 }
064 fileReader.close();
065 }
066 }
http://files.cnblogs.com/nokiaguy/designpatterns.rar designpatterns.rar 4096
http://files.cnblogs.com/nokiaguy/download.rar download.rar 8192
国内最棒的Google Android技术社区(eoeandroid),欢迎访问!
《银河系列原创教程》发布
《Java Web开发速学宝典》出版,欢迎定购
Java网络编程从入门到精通(24):实现HTTP断点续传下载工具(附源代码)相关推荐
- java消息头,Java网络编程从入门到精通:HTTP消息头字段
Java网络编程从入门到精通:HTTP消息头字段 一.通用头字段 1. Connection 这个字段只在HTTP1.1协议中存在.它决定了客户端和服务器进行了一次会话后, 服务器是否立即关闭网络连接 ...
- Java网络编程从入门到精通(1):Internet地址概述
所有连入Internet的终端设备(包括计算机.PDA.打印机以及其他的电子设备)都有一个唯一的索引,这个索引被称为IP地址.现在Internet上的IP地址大多由四个字节组成,这种IP地址叫做IPv ...
- Java网络编程从入门到精通(14):多种多样的建立网络连接的方式
在上一篇文章中我们讨论了Socket类的基本用法,并给出的例子中使用Socket类连接服务器时使用了一种最简单的连接方式,也就是通过IP和端口号来连接服务器.而为了使连接服务器的方式更灵活,Socke ...
- Java网络编程从入门到精通(25):创建ServerSocket对象
ServerSocket类的构造方法有四种重载形式,它们的定义如下: public ServerSocket() throws IOException public ServerSocket(int ...
- Java网络编程从入门到精通 (9):使用isXxx方法判断地址类型
IP地址分为普通地址和特殊地址.在前面的文章中所使用的大多数都是普通的IP地址,在本文中将介绍如何利用InetAddress类提供的十个方法来确定一个IP地址是否是一个特殊的IP地址. 一.isAn ...
- Java网络编程从入门到精通(4):DNS缓存
在通过DNS查找域名的过程中,可能会经过多台中间DNS服务器才能找到指定的域名,因此,在DNS服务器上查找域名是非常昂贵的操作.在Java中为了缓解这个问题,提供了DNS缓存.当InetAddress ...
- Java网络编程从入门到精通(2):创建InetAddress对象的四个静态方法
InetAddress类是Java中用于描述IP地址的类.它在java.net包中.在Java中分别用Inet4Address和Inet6Address类来描述IPv4和IPv6的地址.这两个类都是I ...
- Java网络编程从入门到精通(3):为什么不能直接通过IP访问网站
在<创建InetAdrress对象的四个静态方法>一文中通过getAllByName得到了www.csdn.net对应的四个IP地址.从理论上说,在IE(或其他的Web浏览器,如Fire ...
- Java网络编程从入门到精通(7):用getHostAddress方法获得IP地址
这个方法用来得到主机的IP地址,这个IP地址可能是IPv4的地址,也可能是IPv6的地址.getHostAddress方法的定义如下: public String getHostAddress() ...
最新文章
- python操作sqlserver如何判断删除的数据不存在_Python MongoDB 插入数据时已存在则不执行,不存在则插入的解决方法...
- traceback异常打印
- 《PRML_Translation》pdf
- c++ linux 线程等待与唤醒_Linux线程同步(互斥量、信号量、条件变量、生产消费者模型)...
- 【转】UINavigationBar 使用总结
- 找礼物(find)(模拟)
- 第二次冲刺-站立会议06
- mysql java dbutil_Java -- DBUtils 框架 操作MySQL数据库
- Dubbo服务暴露(导出)流程
- 线程安全的set_「Java」 - 多线程四 amp; ThreadLocal
- NHOI2019总结
- C语言之父丹尼斯·里奇:乔布斯脚下的巨人肩膀
- 魔兽8.0最新服务器人口普查,魔兽世界8.2最新人口普查 2019各服务器人口普查信息汇总...
- 阿里云部署网站全流程(基于nodejs)
- DNS域名解析过程剖析
- WordPress强大多功能主题模板The7 v9.16.0 已激活版本完全兼容大多数插件
- 用 JAVA 实现微信第三方登录
- 2020最新安卓版本是多少_百度浏览器2020最新版本下载,百度浏览器2020官方最新版本下载安装 v7.19.13.0...
- WDK10编译出最适合申请WHQL认证的驱动
- 验证码识别PaddleOCR 快速开始
热门文章
- centos 指定文件路径 脚本_centos自动删除三天前文件的脚本和自动进入指定目录运行命令...
- shell 启动java程序_Shell 脚本启动java程序
- dbforge连接mysql_DbForge Schema Compare for MySQL入门教程:如何连接到数据库
- velocity(vm)模板引擎学习介绍及语法
- android 寺库trytry_寺库与美图达成战略合作美图美妆APP将由TryTry运营_联商网
- R并行做大数据时间序列分析与bootstrap
- 7wifi模块多少钱_APP开发要多少钱?创业者估算成本的四个方法
- 电流电压曲线 vc源码_电瓶修复—充电曲线你知道多少?
- python哪些是可变对象_python 中的可变对象与不可变对象
- 安装webpack-cli时遇到的问题