断点续传(大文件的下载)后台功能实现
某网盘:
- 可以随时暂停、启动
- 多任务
- 下载过程中、由于某一些特殊原因(宕机、断电、断网等),导致文件下载失败
- 再一次下载的时候,还可以继续在原来的基础上下载
- 当上一次下载的20%,再一次下载的时候,从20%继续下载
- 本地都会产生一个临时数据文件
- 中断后,文件不会消失
断点续传
原理:
实现:
长连接:socket、urlconnection、http、okhttp、httpclient
思路:
- 指定URL
- 建立一个目录(指定临时文件)
- 从服务器中获取对象流
- 告诉服务器从哪个位置下标,开始发送数据
- 将对象流对象,写入到临时文件中
- 根据读取到的对象流长度来进行定义
- 如果长度有值,则进行写入
- 如果长度=-1,则无需进行写入操作
代码:
/** * * @author: likang * @date: 2019/12/5 20:44 * @description: 断点续传(仿百度网盘下载功能) */ public class FileDownLoadUtils { public static void main(String[] args) { //指定URL String url = "http://mirrors.aliyun.com/centos/8.0.1905/isos/x86_64/CentOS-8-x86_64-1905-dvd1.iso"; //下载文件 downLoadFile(url); } /* * @Description: 创建文件 * @author: likang * @date: 2019/12/5 20:47 * @params: [url] * @return: void * @exception: */ private static void downLoadFile(String url) { //指定本地下载的目录地址 File file = new File(FileDownLoadUtils.class.getResource("").getFile()); // //生成一个临时文件(目的:主要是记录数据的下标位置(字节长度)) // //getAbsolutePath:获取绝对路径 // //separator:自动识别当前系统资源分割符合 file = new File(file.getAbsolutePath() + File.separator + "CentOS-8-x86_64-1905-dvd1.iso.bak"); //如果目录不存在,则创建 if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } //将url中的数据流对象,写入到临时文件中file writeFile(url,file); } /* * @Description: 通过url获取服务器对象流,并写入到文件中file * @author: likang * @date: 2019/12/5 21:00 * @params: [url, file] * @return: void * @exception: */ private static void writeFile(String url, File file) { byte[] bytes = new byte[1024*1024]; //定义流对象 InputStream inputStream = null;//数据流 FileOutputStream fileOutputStream = null;//写入file对象数据流 long fileLength = 0; int byteCount = 0; //根据URL和服务器建立连接---数据流 try { fileOutputStream = new FileOutputStream(file, true); fileLength = file.length(); //建立连接,获取对象流 inputStream = getInputStream(url,fileLength); // byteCount = inputStream.read(bytes); // while(byteCount != -1){ // //数据流---file文件中(临时文件) // fileOutputStream.write(bytes, 0, byteCount); // } while((byteCount = inputStream.read(bytes)) != -1){ //数据流---file文件中(临时文件) fileOutputStream.write(bytes, 0, byteCount); } } catch (Exception e) { e.printStackTrace(); }finally { //关闭流对象 try { inputStream.close(); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /* * @Description: 建立连接、获取对象流 * @author: likang * @date: 2019/12/5 21:18 * @params: [url, fileLength] * @return: java.io.InputStream * @exception: */ private static InputStream getInputStream(String url, long startFileLength) { InputStream inputStream = null; HttpURLConnection connection; try { URL filePath = new URL(url);//和服务器建立连接、获取文件路径 connection = (HttpURLConnection) filePath.openConnection();//开启连接 connection.setConnectTimeout(3*1000);//连接超时时间 long lengthLong = connection.getContentLengthLong();//文件的总长度 if(startFileLength < lengthLong){//还没下载完毕 connection.disconnect();//销毁链接 connection = (HttpURLConnection) filePath.openConnection();//开启连接 connection.setConnectTimeout(3*1000);//连接超时时间 connection.setRequestProperty("RANGE", "bytes=" + startFileLength + "-");//设置请求发送下标的对象 System.out.println(connection.getContentLengthLong()); inputStream = connection.getInputStream(); } } catch (Exception e) { e.printStackTrace(); } return inputStream; } }