package com.smart.impl;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.util.Log;
import com.smart.db.FileService;
/**
* 文件下载器
* @author lihuoming@sohu.com
*/
public class SmartFileDownloader {
private static final String TAG = "SmartFileDownloader";
private Context context;
private FileService fileService;
/* 已下载文件长度 */
private int downloadSize = 0;
/* 原始文件长度 */
private int fileSize = 0;
/* 线程数 */
private SmartDownloadThread[] threads;
/* 本地保存文件 */
private File saveFile;
/* 缓存各线程下载的长度*/
private Map<Integer, Integer> data = new ConcurrentHashMap<Integer, Integer>();
/* 每条线程下载的长度 */
private int block;
/* 下载路径 */
private String downloadUrl;
/**
* 获取线程数
*/
public int getThreadSize() {
return threads.length;
}
/**
* 获取文件大小
* @return
*/
public int getFileSize() {
return fileSize;
}
/**
* 累计已下载大小
* @param size
*/
protected synchronized void append(int size) {
downloadSize += size;
}
/**
* 更新指定线程最后下载的位置
* @param threadId 线程id
* @param pos 最后下载的位置
*/
protected void update(int threadId, int pos) {
this.data.put(threadId, pos);
}
/**
* 保存记录文件
*/
protected synchronized void saveLogFile() {
this.fileService.update(this.downloadUrl, this.data);
}
/**
* 构建文件下载器
* @param downloadUrl 下载路径
* @param fileSaveDir 文件保存目录
* @param threadNum 下载线程数
*/
public SmartFileDownloader(Context context, String downloadUrl, File fileSaveDir, int threadNum) {
try {
this.context = context;
this.downloadUrl = downloadUrl;
fileService = new FileService(this.context);
URL url = new URL(this.downloadUrl);
if(!fileSaveDir.exists()) fileSaveDir.mkdirs();
this.threads = new SmartDownloadThread[threadNum];
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.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, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Referer", downloadUrl);
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.connect();
printResponseHeader(conn);
if (conn.getResponseCode()==200) {
this.fileSize = conn.getContentLength();//根据响应获取文件大小
if (this.fileSize <= 0) throw new RuntimeException("Unkown file size ");
String filename = getFileName(conn);
this.saveFile = new File(fileSaveDir, filename);/* 保存文件 */
Map<Integer, Integer> logdata = fileService.getData(downloadUrl);
if(logdata.size()>0){
for(Map.Entry<Integer, Integer> entry : logdata.entrySet())
data.put(entry.getKey(), entry.getValue());
}
this.block = (this.fileSize % this.threads.length)==0? this.fileSize / this.threads.length : this.fileSize / this.threads.length + 1;
if(this.data.size()==this.threads.length){
for (int i = 0; i < this.threads.length; i++) {
this.downloadSize += this.data.get(i+1);
}
print("已经下载的长度"+ this.downloadSize);
}
}else{
throw new RuntimeException("server no response ");
}
} catch (Exception e) {
print(e.toString());
throw new RuntimeException("don't connection this url");
}
}
/**
* 获取文件名
*/
private String getFileName(HttpURLConnection conn) {
String filename = this.downloadUrl.substring(this.downloadUrl.lastIndexOf('/') + 1);
if(filename==null || "".equals(filename.trim())){//如果获取不到文件名称
for (int i = 0;; i++) {
String mine = conn.getHeaderField(i);
if (mine == null) break;
if("content-disposition".equals(conn.getHeaderFieldKey(i).toLowerCase())){
Matcher m = Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase());
if(m.find()) return m.group(1);
}
}
filename = UUID.randomUUID()+ ".tmp";//默认取一个文件名
}
return filename;
}
/**
* 开始下载文件
* @param listener 监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null
* @return 已下载文件大小
* @throws Exception
*/
public int download(SmartDownloadProgressListener listener) throws Exception{
try {
RandomAccessFile randOut = new RandomAccessFile(this.saveFile, "rw");
if(this.fileSize>0) randOut.setLength(this.fileSize);
randOut.close();
URL url = new URL(this.downloadUrl);
if(this.data.size() != this.threads.length){
this.data.clear();//清除数据
for (int i = 0; i < this.threads.length; i++) {
this.data.put(i+1, 0);
}
}
for (int i = 0; i < this.threads.length; i++) {
int downLength = this.data.get(i+1);
if(downLength < this.block && this.downloadSize<this.fileSize){ //该线程未完成下载时,继续下载
this.threads[i] = new SmartDownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
this.threads[i].setPriority(7);
this.threads[i].start();
}else{
this.threads[i] = null;
}
}
this.fileService.save(this.downloadUrl, this.data);
boolean notFinish = true;//下载未完成
while (notFinish) {// 循环判断是否下载完毕
Thread.sleep(900);
notFinish = false;//假定下载完成
for (int i = 0; i < this.threads.length; i++){
if (this.threads[i] != null && !this.threads[i].isFinish()) {
notFinish = true;//下载没有完成
if(this.threads[i].getDownLength() == -1){//如果下载失败,再重新下载
this.threads[i] = new SmartDownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
this.threads[i].setPriority(7);
this.threads[i].start();
}
}
}
if(listener!=null) listener.onDownloadSize(this.downloadSize);
}
fileService.delete(this.downloadUrl);
} catch (Exception e) {
print(e.toString());
throw new Exception("file download fail");
}
return this.downloadSize;
}
/**
* 获取Http响应头字段
* @param http
* @return
*/
public static Map<String, String> getHttpResponseHeader(HttpURLConnection http) {
Map<String, String> header = new LinkedHashMap<String, String>();
for (int i = 0;; i++) {
String mine = http.getHeaderField(i);
if (mine == null) break;
header.put(http.getHeaderFieldKey(i), mine);
}
return header;
}
/**
* 打印Http头字段
* @param http
*/
public static void printResponseHeader(HttpURLConnection http){
Map<String, String> header = getHttpResponseHeader(http);
for(Map.Entry<String, String> entry : header.entrySet()){
String key = entry.getKey()!=null ? entry.getKey()+ ":" : "";
print(key+ entry.getValue());
}
}
//打印日志
private static void print(String msg){
Log.i(TAG, msg);
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
小程序源码 网络浏览 多线程断点下载源码.rar
共36个文件
class:16个
java:7个
png:3个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 120 浏览量
2023-03-29
19:54:29
上传
评论
收藏 80KB RAR 举报
温馨提示
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累成果,供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,本人不对所涉及的版权问题或内容负法律责任。如有侵权,请举报或通知本人删除。
资源推荐
资源详情
资源评论
收起资源包目录
小程序源码 网络浏览 多线程断点下载源码.rar (36个子文件)
Android 多线程断点下载源码
.classpath 280B
assets
src
com
smart
activoty
download
SmartDownloadActivity.java 3KB
impl
SmartDownloadProgressListener.java 120B
SmartDownloadThread.java 3KB
SmartFileDownloader.java 7KB
db
DBOpenHelper.java 791B
FileService.java 2KB
res
drawable-mdpi
icon.png 3KB
drawable-ldpi
icon.png 2KB
values
strings.xml 449B
layout
main.xml 1KB
drawable-hdpi
icon.png 4KB
bin
resources.ap_ 11KB
classes.dex 17KB
smart_breakpointDownload.apk 21KB
com
smart
activoty
download
SmartDownloadActivity$3.class 2KB
R$string.class 607B
SmartDownloadActivity.class 3KB
R$layout.class 421B
R$id.class 504B
SmartDownloadActivity$2.class 2KB
SmartDownloadActivity$3$1.class 1KB
R$attr.class 367B
R$drawable.class 427B
R.class 594B
SmartDownloadActivity$1.class 2KB
impl
SmartDownloadThread.class 4KB
SmartFileDownloader.class 8KB
SmartDownloadProgressListener.class 186B
db
FileService.class 3KB
DBOpenHelper.class 1KB
proguard.cfg 1KB
default.properties 362B
.project 860B
AndroidManifest.xml 1KB
gen
com
smart
activoty
download
R.java 1KB
共 36 条
- 1
资源评论
荣华富贵8
- 粉丝: 150
- 资源: 7649
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功