最近一直在做视频这块的一个拓展应用,其中涉及到视频下载、视频静止内容分析、视频语音识别文字等方面的应用,其中最关键的是要从存储服务器获取当前需要操作的视频,所以就写了个视频下载的一个小模块,现分享给大家,希望能帮到一些有类似需求的童鞋们,有其它的一些需求的,也可以在我的代码的基础上去修改,也欢迎大家给我指出不足,共同进步,代码如下:
首先要获取 HttpURLConnection 连接,创建一个HttpConnectionUtil.java这个类:
package com.wal.utils.downloadutils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 获取 HttpURLConnection 连接
* @author wal
* @date 2019/5/22
*/
public class HttpConnectionUtil {
// 记录读取了多少,一共读取了多少
private long start;
// 记录文件总大小
private long sum;
public long getStart() {
return start;
}
public void setStart(long start) {
this.start = start;
}
public long getSum() {
return sum;
}
public void setSum(long sum) {
this.sum = sum;
}
/**
*
* @Title: getHttpConnection
* @Description: 获取 url 连接
* @param: @param urlLocation
* @param: @return HttpURLConnection实例化对象
* @param: @throws IOException
* @return: HttpURLConnection
* @throws
*/
public static HttpURLConnection getHttpConnection(String urlLocation) throws IOException {
URL url = new URL(urlLocation);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
return conn;
}
}
然后创建一个文件下载类DownloadFileRang.java,集成Runnable 实现多线程:
package com.wal.utils.downloadutils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
/**
* 文件下载类,此处使用 继承 Runnable 实现多线程
* @author wal
* @date 2019/5/22
*/
public class DownloadFileRang implements Runnable {
// 文件开始位置
private long start ;
// 文件结束位置
private long end;
// url地址
private String urlLocation;
// 文件存储位置
private String filePath;
private HttpConnectionUtil httpConnectionUtil;
public HttpConnectionUtil getHttpConnectionUtil() {
return httpConnectionUtil;
}
public void setHttpConnectionUtil(HttpConnectionUtil httpConnectionUtil) {
this.httpConnectionUtil = httpConnectionUtil;
}
public DownloadFileRang(long start, long end, String urlLocation, String filePath, HttpConnectionUtil httpConnectionUtil) {
super();
this.start = start;
this.end = end;
this.urlLocation = urlLocation;
this.filePath = filePath;
this.httpConnectionUtil = httpConnectionUtil;
}
@Override
public void run() {
HttpURLConnection conn = null;
InputStream is = null;
RandomAccessFile out = null;
try {
// 获取连接
conn = httpConnectionUtil.getHttpConnection(urlLocation);
// 设置获取资源范围
conn.setRequestProperty("Range", "bytes=" + start +"-"+end );
File file = new File(filePath);
if(file!=null) {
out = new RandomAccessFile(file, "rw");
}
out.seek(start);
// 获取网络连接的 输入流
is = conn.getInputStream();
byte [] data = new byte[1024];
int len = 0;
while( (len = is.read(data))!=-1 ) {
out.write(data, 0, len);
synchronized (HttpConnectionUtil.class) {
httpConnectionUtil.setStart(httpConnectionUtil.getStart()+len);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 关闭连接
try {
out.close();
is.close();
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文件切片,分别指定 起始点,创建DownloadFilePool.java
package com.wal.utils.downloadutils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 文件切片,分别指定 起始点,注意这里的起始点是包头也包尾的,0-10/11-20/21-30 这种
* @author wal
* @date 2019/5/22
*/
public class DownloadFilePool {
// 网络资源路径
private String urlLocation;
// 存储路径
private String filePath;
// 多少个线程
private int poolLength;
private DownloadFileRang downloadFileRang;
public DownloadFilePool(String urlLocation, String filePath, int poolLength) {
super();
// 如果 保存路径为空则默认存在 D盘,文件名跟下载名相同
if( filePath==null ) {
String fileName = urlLocation.substring( urlLocation.lastIndexOf("/") +1);
filePath = "D:/ZZZ/" + fileName;
}
this.urlLocation = urlLocation;
this.filePath = filePath;
this.poolLength = poolLength;
}
public DownloadFileRang getDownloadFileRang() {
return downloadFileRang;
}
public void setDownloadFileRang(DownloadFileRang downloadFileRang) {
this.downloadFileRang = downloadFileRang;
}
public void getFile() {
HttpConnectionUtil httpConnectionUtil = new HttpConnectionUtil();
try {
// 获取文件长度
long fileLength = httpConnectionUtil.getHttpConnection(urlLocation).getContentLengthLong();
httpConnectionUtil.setSum(fileLength) ;
ExecutorService pool = Executors.newCachedThreadPool();
// 获取每片大小
long slice = fileLength/poolLength;
for(int i = 0 ;i < poolLength; i++) {
long start = i*slice;
long end = (i+1)*slice -1;
if(i==poolLength-1) {
start = i*slice;
end = fileLength ;
}
System.out.println( start + "---" + end );
// 创建下载类
downloadFileRang = new DownloadFileRang(start, end, urlLocation, filePath, httpConnectionUtil);
// 执行线程
pool.execute(downloadFileRang);
}
// 关闭线程池
pool.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
最后在service层调用此工具类:
public void download(Integer filecode, String url, String filename){
//判断文件夹是否存在,不存在创建
File targetFile = new File(BasePath);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(() -> {
/** 下载到本地 开始**/
long begin_time = new Date().getTime();
String videoRealPath = null;
long time = 0;
try {
videoRealPath = BasePath+filename;
File newTargetFile = new File(videoRealPath);//判断是否存在,存在删除后继续下载
if (newTargetFile.exists()) {
newTargetFile.delete();
}
DownloadFilePool pool = new DownloadFilePool(url, videoRealPath, 100);
pool.getFile();
long old = 0;
long now = 0;
while (pool.getDownloadFileRang().getHttpConnectionUtil().getSum() >= pool.getDownloadFileRang().getHttpConnectionUtil().getStart()) {
now = pool.getDownloadFileRang().getHttpConnectionUtil().getStart() - old;
old = pool.getDownloadFileRang().getHttpConnectionUtil().getStart();
if (pool.getDownloadFileRang().getHttpConnectionUtil().getSum() == pool.getDownloadFileRang().getHttpConnectionUtil().getStart()) {
long t = new Date().getTime() - begin_time;
long seconds = t / 1000;
long minutes = seconds / 60;
long second = seconds % 60;
double speed = ((double) pool.getDownloadFileRang().getHttpConnectionUtil().getSum() / (t / 1000.0)) / 1024.0 / 1024.0;
log.info("下载完成,用时:{}分{}秒,平均网速:{}M/s",minutes,second,speed);
break;
}
System.out.println("网速:" + ((double) (now / 0.5)) / 1024.0 / 1024.0 + " M/s,已完成:" + (pool.getDownloadFileRang().getHttpConnectionUtil().getStart() / (double) pool.getDownloadFileRang().getHttpConnectionUtil().getSum()) * 100 + "%");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/** 下载到本地 结束**/
} catch (Exception e) {
System.out.println("文件:"+filename+",下载失败");
log.error(e.getMessage());
}
});
executor.shutdown();
}
有不懂的地方可以给我留言,或者进群交流!