【Java】之 写个线程下载文件(支持断点续传)
来源:互联网 发布:情定三生向天和知夏 编辑:程序博客网 时间:2024/06/05 17:16
持续更新。。。
本文分三次完成。
Step 1
实现功能:
实现基本下载,参数封装。
学习方面:
IO,URL, URLConnection, HTTPsConnection
public class DownUtils { private final String url; private final String fileName; private final String targetDir; public DownUtils(String url, String fileName, String targetDir){ this.url = url; this.fileName = fileName; this.targetDir = targetDir; } public DownUtils(String url,String fileName){ this.url = url; this.fileName = fileName; this.targetDir = ""; } public void makeSureDir(){ File targetDir = new File(this.targetDir); if(!targetDir.exists()) targetDir.mkdir(); } public String getFileName(){ if (!"".equals(targetDir)){ makeSureDir(); return targetDir + File.separator + fileName; } return fileName; } public void down(){ try( RandomAccessFile raf = new RandomAccessFile(getFileName(), "rw") ) { URL url = new URL(this.url); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setConnectTimeout(8000); connection.setRequestMethod("GET"); //防止屏蔽程序抓取而返回403错误 connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); connection.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); connection.setRequestProperty("Accept-Language", "zh-CN"); connection.setRequestProperty("Charset", "UTF-8"); InputStream inputStream = connection.getInputStream(); byte[] buffer = new byte[1024]; int hasRead = 0; while((hasRead = inputStream.read(buffer)) > 0){ raf.write(buffer, 0, hasRead); } System.out.println("info:" + url + " download success"); } catch (IOException e){ e.printStackTrace(); } } public static void main(String[] args) { DownUtils downUtils = new DownUtils("http://101.95.48.97:8005/res/upload/interface/apptutorials/manualstypeico/6f83ce8f-0da5-49b3-bac8-fd5fc67d2725.png" , "yyf.png", "C:\\Users\\donal\\Desktop\\tools"); downUtils.down(); }}
Step 2
实现功能:
多线程下载
学习方面:
thread
思想:按线程数将一个文件分成若干份,每个线程执行其中的一份。
package cn.Down;/** * Created by donal on 2017/2/21. */import java.io.*;import java.net.HttpURLConnection;import java.net.URL;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 实现多线程下载文件,支持断点续传 * * 1.多线程 * 2.下载:IO流 * 3.断点续传:RandomAccessFile * 4.下载:URL * * step1: 实现文件下载 * (step1,2 同时实现代码封装、整洁) * step2: 多线程下载 * step3: 实现断点续传 */public class DownUtils { private final int fileSize; private final String url; private final String fileName; private final String targetDir; private final int threadSize; private final ExecutorService executorService; public DownUtils(String url, String fileName, String targetDir, int threadSize){ this.url = url; this.fileName = fileName; this.targetDir = targetDir; this.threadSize = threadSize; executorService = Executors.newFixedThreadPool(threadSize); fileSize = getConnection(url).getContentLength(); } public DownUtils(String url,String fileName, int threadSize){ this.url = url; this.fileName = fileName; this.threadSize = threadSize; this.targetDir = ""; executorService = Executors.newFixedThreadPool(threadSize); fileSize = getConnection(url).getContentLength(); } public DownUtils(String url, String fileName){ this.url = url; this.fileName = fileName; this.targetDir = ""; this.threadSize = 1; executorService = Executors.newFixedThreadPool(threadSize); fileSize = getConnection(url).getContentLength(); } public void makeSureDir(){ File targetDir = new File(this.targetDir); if(!targetDir.exists()) targetDir.mkdir(); } public String getFileName(){ if (!"".equals(targetDir)){ makeSureDir(); return targetDir + File.separator + fileName; } return fileName; } public static HttpURLConnection getConnection(String urlPath) { try { URL url = new URL(urlPath); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setConnectTimeout(8000); connection.setRequestMethod("GET"); //防止屏蔽程序抓取而返回403错误 connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); connection.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); connection.setRequestProperty("Accept-Language", "zh-CN"); connection.setRequestProperty("Charset", "UTF-8"); return connection; } catch (IOException e){ e.printStackTrace(); throw new RuntimeException(e); } } public int getFileSize(){ return fileSize; } public void download(){ int partFileSize = fileSize / threadSize + 1; int startPos = 0; for (int i = 0 ; i < threadSize; ++i){ executorService.execute(new DownThread(i, startPos, partFileSize)); startPos += partFileSize; } executorService.shutdown(); } private class DownThread implements Runnable{ private final int threadId; private final int startPos; private final int partFileSize; public DownThread(int threadId, int startPos, int partFileSize){ this.threadId = threadId; this.startPos = startPos; this.partFileSize = partFileSize; } public void writePartFile(){ try ( InputStream inputStream = getConnection(url).getInputStream(); RandomAccessFile raf = new RandomAccessFile(getFileName(), "rw") ) { byte[] buffer = new byte[1024]; int hasRead; int length = 0; inputStream.skip(startPos); raf.seek(startPos); while((length < partFileSize) && (hasRead = inputStream.read(buffer)) > 0){ raf.write(buffer, 0, hasRead); length += hasRead; } } catch (IOException e){ e.printStackTrace(); } } @Override public void run(){ System.out.println("#" + threadId + " is loading..."); writePartFile(); System.out.println("#" + threadId + " succeeded!"); } }}
package cn.Down;/** * Created by donal on 2017/2/23. */public class DownUtilsTest { public static void main(String[] args) { DownUtils downUtils = new DownUtils("http://p1.gexing.com/G1/M00/C8/77/rBACJlYnjHzxEOY2AAC9B6vX98g105.jpg" , "ais.jpg", 5); downUtils.download(); /*new Thread(new Runnable() { @Override public void run() { while(downUtils.getCompleteRate() <1 ){ System.out.println("已完成:" + downUtils.getCompleteRate()); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } });*/ }}
Step 3
实现功能:
实现断点续传(只定义了接口)
学习方面:
File, IO。
思想:按线程名创建对应的临时文件,若要暂停或者退出,则调用setBreakPoint()函数,对临时文件写入startPos,endPos。
疑惑:如何控制线程(比如控制线程生命周期,即destroy)
结果图:
package cn.Down;/** * Created by donal on 2017/2/21. */import java.io.*;import java.net.HttpURLConnection;import java.net.URL;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class DownUtils { private final long fileSize; private final int threadSize; private final String url; private final String fileName; private final String targetDir; private final ExecutorService executorService; public DownUtils(String url, String fileName, String targetDir, int threadSize){ this.url = url; this.fileName = fileName; this.targetDir = targetDir; this.threadSize = threadSize; executorService = Executors.newFixedThreadPool(threadSize); fileSize = getConnection(url).getContentLength(); } public DownUtils(String url,String fileName, int threadSize){ this.url = url; this.fileName = fileName; this.threadSize = threadSize; this.targetDir = ""; executorService = Executors.newFixedThreadPool(threadSize); fileSize = getConnection(url).getContentLength(); } public DownUtils(String url, String fileName){ this.url = url; this.fileName = fileName; this.targetDir = ""; this.threadSize = 1; executorService = Executors.newFixedThreadPool(threadSize); fileSize = getConnection(url).getContentLength(); } private void makeSureDir(){ File targetDir = new File(this.targetDir); if(!targetDir.exists()) targetDir.mkdir(); } public String getFileName(){ if (!"".equals(targetDir)){ makeSureDir(); return targetDir + File.separator + fileName; } return fileName; } private static HttpURLConnection getConnection(String urlPath) { try { URL url = new URL(urlPath); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setConnectTimeout(8000); connection.setRequestMethod("GET"); //防止屏蔽程序抓取而返回403错误 connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); connection.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, " + "application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*"); connection.setRequestProperty("Accept-Language", "zh-CN"); connection.setRequestProperty("Charset", "UTF-8"); return connection; } catch (IOException e){ e.printStackTrace(); throw new RuntimeException("get connection default."); } } private File fileFactory(String fileName){ return new File(fileName); } private boolean isFileExist(){ File targetFile = fileFactory(getFileName()); if (targetFile.exists() && targetFile.length() == fileSize){ System.out.println("The file you want to download has existed!!"); return true; } return false; } private void createThread(){ long partFileSize = fileSize / threadSize + 1; long startPos = 0; for (int i = 0 ; i < threadSize; ++i){ executorService.execute(new DownThread(i, startPos, partFileSize)); startPos += partFileSize; } executorService.shutdown(); } public void download(){ if (isFileExist()) return; System.out.println(url + " is ready to download.----------"); createThread(); } private class DownThread implements Runnable{ private long threadId; private long startPos; private long endPos; private long partFileSize; private final String tempFileName; private transient File tempFile; public DownThread(int threadId, long startPos, long partFileSize) { this.threadId = threadId; this.startPos = startPos; this.partFileSize = partFileSize; endPos = partFileSize + startPos; tempFileName = "temp" + threadId + ".txt"; } public void writePartFile(){ try ( InputStream inputStream = getConnection(url).getInputStream(); RandomAccessFile raf = new RandomAccessFile(getFileName(), "rw") ) { byte[] buffer = new byte[1024]; int hasRead; inputStream.skip(startPos); raf.seek(startPos); int length = 0; while((length < partFileSize) && (hasRead = inputStream.read(buffer)) > 0){ raf.write(buffer, 0, hasRead); startPos += hasRead; } tempFile.deleteOnExit(); } catch (IOException e){ throw new RuntimeException("write part file default."); } } private void readTempFile(){ try( RandomAccessFile raf = new RandomAccessFile(tempFileName, "rw") ) { raf.seek(0); startPos = raf.readLong(); raf.seek(8); endPos = raf.readLong(); partFileSize = endPos - startPos; } catch (IOException e){ throw new RuntimeException("read from temp file default."); } } private void createTempFile() { try { tempFile = File.createTempFile(tempFileName, null); } catch (IOException e) { throw new RuntimeException("create new file default."); } } public void makeSureTempFileExist() { tempFile = new File(tempFileName); if (tempFile.exists()){ readTempFile(); }else { createTempFile(); } } private void setBreakPoint(){ try( RandomAccessFile raf = new RandomAccessFile(tempFileName, "rw") ) { raf.writeLong(startPos); raf.writeLong(endPos); } catch (IOException e){ e.printStackTrace(); throw new RuntimeException("set break-point default."); } } @Override public void run(){ System.out.println("#" + threadId + "---Thread is loading..."); makeSureTempFileExist(); writePartFile(); System.out.println("#" + threadId + "---Thread succeeded!"); } }}
package cn.Down;/** * Created by donal on 2017/2/23. */public class DownUtilsTest { public static void main(String[] args) { DownUtils downUtils = new DownUtils("https://gss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/zhidao/pic/item/d1a20cf431adcbef25b551dfaaaf2edda2cc9f61.jpg" , "ais2.jpg", 5); downUtils.download(); /*new Thread(new Runnable() { @Override public void run() { while(downUtils.getCompleteRate() <1 ){ System.out.println("已完成:" + downUtils.getCompleteRate()); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } });*/ }}
1 0
- 【Java】之 写个线程下载文件(支持断点续传)
- 单线程支持断点续传文件下载
- Java 文件下载(支持断点续传)(实例2)
- 利用Winsock下载文件(支持断点续传)
- 利用Winsock下载文件(支持断点续传)
- java多线程下载网络资源(支持断点续传)
- Java Web 文件下载之断点续传
- Java 下载支持断点续传服务端
- java 文件下载 断点续传
- java文件下载断点续传
- java支持断点续传文件上传和下载组件
- 让自定义文件下载支持断点续传(HTTP_RANGE Adodb.Stream)
- 自定义文件下载支持断点续传(HTTP_RANGE Adodb.Stream)
- Android下载服务器资源文件(支持断点续传)
- 多线程下载文件(支持暂停、取消、断点续传)
- 多线程下载文件(支持暂停、取消、断点续传)
- 多线程下载文件(支持暂停、取消、断点续传)
- 多线程下载文件(支持暂停、取消、断点续传)
- 大家快来A水题
- http code状态码,错误码
- VBA中msgbox的用法小结
- CS0120号错误是什么
- SOA 的安全挑战
- 【Java】之 写个线程下载文件(支持断点续传)
- 使用Maven配置Tomcat插件
- Android语音文件speex编码解码(一)
- QML设置窗口背景
- C# listview控件
- PAT 1023 组个最小数(2)
- [LeetCode] 3Sum 解题报告
- Java——制作工具类说明书(注释)
- 大数据学习笔记之四十 数据挖掘算法之预测建模关于决策树模型的介绍