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

时间:2022-02-02 11:40:51

前言:

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

文件下载的断点续传:

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

    2、http请求时设置Range参数

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

直接上代码:

 package com.test.service;

 import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.NumberFormat; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; /**
* <p>
* 文件下载,可以支持断点续传
* 暂未使用
* </p>
* @author
* @version 1.0
* */
@Component
public class DownloadOnly { private static final Logger logger = LoggerFactory.getLogger(DownloadOnly.class); @Value("${onair.download.ddxc:true}")
boolean ddxc = true; int startIndex = 0; long downloadSize = 0; boolean downloadFinish = false; int totleSize = 0; public boolean download(String url,String file_path,int downloadTimeout){ //起一个线程 检测下载进度
new Thread(new Runnable() { @Override
public void run() {
try {
NumberFormat nt = NumberFormat.getPercentInstance();
//设置百分数精确度3即保留三位小数
nt.setMinimumFractionDigits(1);
while(!downloadFinish){
Thread.sleep(30000);
logger.debug("已下载大小{},进度{}",getDownloadSize(),nt.format(getDownloadSize()* 1.0 /totleSize));
}
} catch (InterruptedException e) {
e.printStackTrace();
} }
}).start(); logger.info("下载文件:源路径{},目标路径:{}",url,file_path);
RandomAccessFile raf = null;
InputStream in = null; try {
URL file_url = new URL(url);
HttpURLConnection conn = (HttpURLConnection)file_url.openConnection();
conn.setConnectTimeout(downloadTimeout);
conn.setRequestMethod("GET");
File tmpFile = new File(file_path+"_tmp");
if(ddxc){
if(tmpFile.exists() && tmpFile.isFile()){
downloadSize = tmpFile.length();
startIndex = (int)downloadSize;
}
conn.setRequestProperty("Range", "bytes=" + startIndex + "-");
}else{
if(tmpFile.exists() && tmpFile.isFile())
tmpFile.delete();
}
int status = conn.getResponseCode();
totleSize = (int)downloadSize + conn.getContentLength();
logger.info("文件总大小{},下载请求获得的返回状态码:{},需要下载的大小{}",totleSize,status,totleSize-downloadSize);
if(status== 200 || status == 206 ){
raf = new RandomAccessFile(tmpFile, "rwd");
raf.seek(startIndex);
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int size = 0;
while((size=in.read(buffer)) !=-1 ){
raf.write(buffer, 0, size);
downloadSize += size;
}
raf.close();
in.close();
File dest = new File(file_path);
return tmpFile.renameTo(dest);
}
} catch (Throwable e) {
logger.error("文件下载失败:{}",e.getMessage(),e);
}finally {
downloadFinish = true; //下载完成或中断
}
return false;
} public long getDownloadSize() {
return downloadSize;
} public static void main(String[] args) {
DownloadOnly downloadOnly = new DownloadOnly();
} }