URLConnection 类
URLConnection 类:代表应用程序和URL之间的通信链接,此类的实例可用于读取和写入此URL引用的资源,创建到一个URL的连接的步骤
- 通过在 URL 上调用 openConnection 方法创建连接对象
- 处理设置参数和一般请求属性
- 使用connect方法建立到远程对象的实际连接
- 远程对象变为可用,远程对象的头字段和内容变为可访问
参数设置:
- setAllowUserInteraction:是否允许与用户交互,默认 false
- setDoInput:URLConnection可用于输入时设置为true,默认为true
- setDoOutput:URLConnection可用于输出时设置为true,默认为false
- setIfModifiedSince:将放置If-Modified-Since首部字段中的日期(格林威治标准时间1970年1月1日子夜后的毫秒数)
- setUseCaches:是否可以在缓存可用时使用缓存,默认为true,表示缓存将被使用;false表示缓存不被使用
- setConnectTimeout:设置获取连接的超时值,单位为ms
- setReadTimeout:设置获取读取的超时值,单位为ms
- setFollowRedirects(boolean set):true,允许跟随重定向
HttpURLConnecton 类
HttpURLConnection 类:可以实现简单的基于URL请求、响应功能
参数值设置:
- setRequestProperty(String key, String value):在首部设置一个值
- addRequestProperty(String key, String value):用于添加某个指定首部字段的值
- InputStream getInputStream():返回从此打开的连接读取的输入流
- OutputStream getOutputStream():返回写入到此连接的输出流
- setRequestMethod(String method):设置请求方法
- getResponseMessage():返回消息响应
- getResponseCode():返回消息响应码
- setInstanceFollowRedirects(boolean followRedirects):true,允许跟随重定向
- 若只是向服务器请求数据,则为HTTP请求方法为GET
- 若需要向服务器提交数据,必须在先调用setDoOutput(true)。当doOutput属性为true时,请求方法将由GET变为POST
单线程下载器
从给定的地址下载文件,有如下几个要点
- 如果传入的 URL 是一个动态网址,需要获取真实的网址,需要设置 URLConnection.setFollowRedirects(boolean set) 或者 HttpURLConnection.setInstanceFollowRedirects(boolean followRedirects) 允许跟随重定向,然后取得真实的下载地址
- 在下载文件时传入参数需要设置 Content-Length 属性
- 有些下载站可能有防盗链设置,因此最好设置 Referer:网站网址 属性
- 为了避免网站的反爬虫机制,最好添加浏览器代理
如果有需要,可以使用 curl 先进行测试:
- -I:只显示响应头信息
- -L:跟踪重定向
- —header “Referer: http://xiazai.zol.com.cn/“ :设置请求头属性,避免防盗链导致跳转到首页

public class Downloader {private static HttpURLConnection connection(URL url) throws IOException {// 1.获取连接URLConnection urlConnection = url.openConnection();// 2.获取HttpURLConnectionHttpURLConnection connection = (HttpURLConnection) urlConnection;// 3.设置基础的连接参数// 设置Referer参数,避免防盗链connection.setRequestProperty("Referer", url.getHost());// 设置用户代理connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36");// 允许跟踪重定向connection.setInstanceFollowRedirects(true);return connection;}private static String getFileName(URL url) {String path = url.getPath();return path.substring(path.lastIndexOf("/") + 1);}private static volatile int count = 0;private static void downloader(URL url) throws IOException {/* 获取真实的下载地址 */HttpURLConnection connection = connection(url);connection.connect();// 获取文件大小long len = connection.getContentLengthLong();// 获取真实的下载地址URL urlTruth = connection.getURL();// 获取文件名String fileName = getFileName(urlTruth);// 关闭连接connection.disconnect();System.out.println("真实的下载地址:" + urlTruth);System.out.println("文件名:" + fileName);System.out.println("文件大小" + len);/* 开始下载 */HttpURLConnection conn = connection(urlTruth);// 设置Content-Length参数conn.setRequestProperty("Content-Length", String.valueOf(len));conn.connect();try (BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));) {byte[] bytes = new byte[1024];int read = 0;View view = new View();// 设置为守护线程view.setDaemon(true);view.start();while ((read = bis.read(bytes)) != -1) {bos.write(bytes, 0, read);count += read;}bos.flush();}}// 监测线程private static class View extends Thread {@Overridepublic void run() {while (!Thread.interrupted()) {System.out.println("已经下载:" + count / 1024 + "KB");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) throws IOException {URL url = new URL("http://down10.zol.com.cn/20180522/YunGameBoxSetup_dyg1167_yjwzgc.exe");URL url1 = new URL("http://download.skycn.com/hao123-soft-online-bcs/soft/P/2014-05-22_PowerWord.100.exe");URL url2 = new URL("http://xiazai.zol.com.cn/down.php?softid=428117&subcateid=1442&site=10&checkStr=28088c8250a5dcb30&pos=downloader_list&rand=4a6d84");downloader(url2);}}
文件断点续传
文件端点续传实现原理:
- 如果响应头信息中存在“Accept-Ranges:bytes”属性,说明该网站支持断点续传
- 就是在请求时可以通过设置请求头属性“Range:bytes=0-xx”指定服务器传输的位置
以上面获得的真实地址为例,构建 curl 请求:
从上面的响应头信息中可以看到:
- 返回代码变成了 206 Partial Content
- Content-Range 属性变成了 100-1000/33082232
