Java单线程文件下载,支持断点续传功能

前言:

程序下载文件时,有时会因为各种各样的原因下载中断,对于小文件来说影响不大,可以快速重新下载,但是下载大文件时,就会耗费很长时间,所以断点续传功能对于大文件很有必要。

文件下载的断点续传:

  1、先下载临时文件,用于记录已下载大小:

2、http请求时设置Range参数

3、下载此次请求的数据;

直接上代码:

  1 package com.test.service;
  2 
  3 import java.io.File;
  4 import java.io.InputStream;
  5 import java.io.RandomAccessFile;
  6 import java.net.HttpURLConnection;
  7 import java.net.URL;
  8 import java.text.NumberFormat;
  9 
 10 import org.slf4j.Logger;
 11 import org.slf4j.LoggerFactory;
 12 import org.springframework.beans.factory.annotation.Value;
 13 import org.springframework.stereotype.Component;
 14 
 15 /**
 16  * <p>
 17  *     文件下载,可以支持断点续传
 18  *     暂未使用
 19  * </p>
 20  *  @author 
 21  *  @version 1.0
 22  * */
 23 @Component
 24 public class DownloadOnly {
 25 
 26     private static final Logger logger = LoggerFactory.getLogger(DownloadOnly.class);
 27     
 28     @Value("${onair.download.ddxc:true}")
 29     boolean ddxc = true;
 30     
 31     int startIndex = 0;
 32     
 33     long downloadSize = 0;
 34     
 35     boolean downloadFinish = false;
 36     
 37     int totleSize = 0;
 38     
 39     public boolean download(String url,String file_path,int downloadTimeout){
 40 
 41         //起一个线程 检测下载进度
 42         new Thread(new Runnable() {
 43             
 44             @Override
 45             public void run() {
 46                 try {
 47                      NumberFormat nt = NumberFormat.getPercentInstance();  
 48                       //设置百分数精确度3即保留三位小数  
 49                      nt.setMinimumFractionDigits(1);  
 50                     while(!downloadFinish){
 51                         Thread.sleep(30000);
 52                         logger.debug("已下载大小{},进度{}",getDownloadSize(),nt.format(getDownloadSize()* 1.0 /totleSize));
 53                     }
 54                 } catch (InterruptedException e) {
 55                     e.printStackTrace();
 56                 }
 57                 
 58             }
 59         }).start();
 60         
 61         logger.info("下载文件:源路径{},目标路径:{}",url,file_path);
 62         RandomAccessFile raf = null;
 63         InputStream in = null;
 64         
 65         try {
 66             URL file_url = new URL(url);
 67             HttpURLConnection conn = (HttpURLConnection)file_url.openConnection();
 68             conn.setConnectTimeout(downloadTimeout);
 69             conn.setRequestMethod("GET");
 70             File tmpFile = new File(file_path+"_tmp");
 71             if(ddxc){
 72                 if(tmpFile.exists() && tmpFile.isFile()){
 73                     downloadSize = tmpFile.length();
 74                     startIndex = (int)downloadSize;
 75                 }
 76                 conn.setRequestProperty("Range", "bytes=" + startIndex + "-");
 77             }else{
 78                 if(tmpFile.exists() && tmpFile.isFile())
 79                     tmpFile.delete();
 80             }
 81             int status = conn.getResponseCode();
 82             totleSize = (int)downloadSize + conn.getContentLength();
 83             logger.info("文件总大小{},下载请求获得的返回状态码:{},需要下载的大小{}",totleSize,status,totleSize-downloadSize);
 84             if(status== 200 || status == 206 ){
 85                 raf = new RandomAccessFile(tmpFile, "rwd");
 86                 raf.seek(startIndex);
 87                 in = conn.getInputStream();
 88                 byte[] buffer = new byte[1024];
 89                 int size = 0;
 90                 while((size=in.read(buffer)) !=-1 ){
 91                     raf.write(buffer, 0, size);
 92                     downloadSize += size;
 93                 }
 94                 raf.close();
 95                 in.close();
 96                 File dest = new File(file_path);
 97                 return tmpFile.renameTo(dest);
 98             }
 99         } catch (Throwable e) {
100             logger.error("文件下载失败:{}",e.getMessage(),e);
101         }finally {
102             downloadFinish = true; //下载完成或中断
103         }
104         return false;
105     }
106 
107     public long getDownloadSize() {
108         return downloadSize;
109     }
110     
111     public static void main(String[] args) {
112         DownloadOnly downloadOnly = new DownloadOnly();
113     }
114     
115 }