博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
文件多线程下载实现
阅读量:5819 次
发布时间:2019-06-18

本文共 11348 字,大约阅读时间需要 37 分钟。

 

布局文件

1 - 
2 -
3 -
4
5
6
7
8
9
10
11
View Code

 

 

MyHandler.java

1 package com.itheima.download; 2  3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7  8 import org.apache.http.HttpEntity; 9 10 import android.content.Context;11 12 import com.loopj.android.http.FileAsyncHttpResponseHandler;13 14 public abstract class MyFileHandler extends FileAsyncHttpResponseHandler {15     private boolean isCancel;16 17     public MyFileHandler(Context context) {18         super(context);19     }20 21     public MyFileHandler(File file) {22         super(file);23     }24 25     @Override26     protected byte[] getResponseData(HttpEntity entity) throws IOException {27         if (entity != null) {28             InputStream instream = entity.getContent();29             long contentLength = entity.getContentLength();30             FileOutputStream buffer = new FileOutputStream(getTargetFile(), true);31             if (instream != null) {32                 try {33                     byte[] tmp = new byte[BUFFER_SIZE];34                     int l, count = 0;35                     // do not send messages if request has been cancelled36                     while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) {37                         if (isCancel)38                             break;39                         count += l;40                         buffer.write(tmp, 0, l);41                         sendProgressMessage(count, (int) contentLength);42                     }43                 } finally {44                     instream.close();45                     buffer.flush();46                     buffer.close();47                 }48             }49         }50         return null;51     }52     53     public void cancel() {54         isCancel = true;55     }56 57 }
View Code

 

MainActivity.java

1 package com.itheima.download; 2  3 import java.io.File; 4  5 import android.app.Activity; 6 import android.os.Bundle; 7 import android.os.Environment; 8 import android.view.View; 9 import android.widget.EditText;10 import android.widget.ImageButton;11 import android.widget.ProgressBar;12 import android.widget.TextView;13 14 public class MainActivity extends Activity {15 16 //    private AsyncHttpClient client;17     18     private EditText pathET;19     private ProgressBar downloadPB;20     private TextView percentTV;21     private TextView progressTV;22     private DownloadTask task;23 24     @Override25     protected void onCreate(Bundle savedInstanceState) {26         super.onCreate(savedInstanceState);27         setContentView(R.layout.activity_main);28         29         pathET = (EditText) findViewById(R.id.pathET);30         downloadPB = (ProgressBar) findViewById(R.id.downloadPB);31         percentTV = (TextView) findViewById(R.id.percentTV);32         progressTV = (TextView) findViewById(R.id.progressTV);33         34 //        client = new AsyncHttpClient();35     }36     37     public void download(View v) {38         ImageButton ib = (ImageButton) v;39         40         if (task == null) {41             String targetUrl = pathET.getText().toString().trim();42             File localFile = new File(Environment.getExternalStorageDirectory(), targetUrl.substring(targetUrl.lastIndexOf("/") + 1));43             task = new DownloadTask(targetUrl, localFile, 3, this, downloadPB, percentTV, progressTV);44             task.execute();45             ib.setImageResource(android.R.drawable.ic_media_pause);46         } else {47             task.stop();48             task = null;49             ib.setImageResource(android.R.drawable.ic_media_play);50         }51     }52 53     /*54     public void classicDownload(View v) {55         String path = pathET.getText().toString().trim();56         File file = new File("/mnt/sdcard/", path.substring(path.lastIndexOf("/") + 1));57         58         client.get(path, new FileAsyncHttpResponseHandler(file) {        // 处理文件传输的处理器59             public void onSuccess(int statusCode, Header[] headers, File file) {60                 Toast.makeText(getApplicationContext(), "下载成功", Toast.LENGTH_SHORT).show();61             }62             public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) {63                 Toast.makeText(getApplicationContext(), "下载失败 " + statusCode, Toast.LENGTH_SHORT).show();64                 throwable.printStackTrace();65             }66             public void onProgress(int bytesWritten, int totalSize) {    // 下载或上传的进度67                 System.out.println(bytesWritten + " / " + totalSize + " (" + bytesWritten * 100 / totalSize + "%)");68             }69         });70     }71     */72 73 }
View Code

 

DownloadTask.java

1 package com.itheima.download;  2   3 import java.io.File;  4 import java.io.FileInputStream;  5 import java.io.FileOutputStream;  6 import java.io.IOException;  7 import java.util.ArrayList;  8   9 import org.apache.http.Header; 10  11 import android.content.Context; 12 import android.widget.ProgressBar; 13 import android.widget.TextView; 14  15 import com.loopj.android.http.AsyncHttpClient; 16 import com.loopj.android.http.AsyncHttpResponseHandler; 17  18 public class DownloadTask { 19     private String targetUrl; 20     private File localFile; 21     private int threadAmount; 22     private Context context; 23     private ProgressBar downloadPB; 24     private TextView percentTV; 25     private TextView progressTV; 26  27     private long contentLength; 28     private long threadLength; 29     private ArrayList
cacheList = new ArrayList
(); 30 private ArrayList
handlerList = new ArrayList
(); 31 32 /** 33 * 创建下载任务 34 * @param targetUrl 目标地址 35 * @param localFile 本地路径 36 * @param threadAmount 线程数量 37 * @param context 应用环境 38 * @param downloadPB 39 * @param progressTV 40 * @param percentTV 41 */ 42 public DownloadTask(String targetUrl, File localFile, int threadAmount, Context context, ProgressBar downloadPB, TextView percentTV, TextView progressTV) { 43 super(); 44 this.targetUrl = targetUrl; 45 this.localFile = localFile; 46 this.threadAmount = threadAmount; 47 this.context = context; 48 this.downloadPB = downloadPB; 49 this.percentTV = percentTV; 50 this.progressTV = progressTV; 51 } 52 53 public void execute() { 54 new AsyncHttpClient().head(targetUrl, new AsyncHttpResponseHandler() { // 根据URL向服务器发起一个请求, 获取响应头 55 public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { 56 caculateLength(headers); // 获取文件总长度, 计算每个线程负责的长度 57 beginDownload(); // 开启多个线程下载 58 } 59 public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { 60 } 61 }); 62 } 63 64 private void caculateLength(Header[] headers) { 65 for (Header header : headers) 66 if ("Content-Length".equals(header.getName())) 67 contentLength = Long.parseLong(header.getValue()); // 从相应头中获取文件总大小 68 threadLength = (contentLength + threadAmount - 1) / threadAmount; // 计算每个线程负责多少 69 downloadPB.setMax((int) contentLength); // 设置进度条的最大刻度为文件总大小 70 } 71 72 private void beginDownload() { 73 for (int i = 0; i < threadAmount; i++) { // 定义循环, 每次循环启动1个线程下载 74 File cacheFile = new File(context.getCacheDir(), localFile.getName() + ".temp" + i); // 定义临时文件的路径 75 cacheList.add(cacheFile); // 把文件装入集合 76 77 long begin = i * threadLength + cacheFile.length(); // 计算开始位置 78 long end = i * threadLength + threadLength - 1; // 计算结束位置 79 System.out.println(i + ": " + begin + " - " + end); 80 if (begin > end) 81 continue; 82 83 MyFileHandler fileHandler = new MyFileHandler(cacheFile) { // 发送请求, 下载数据, 存储到临时文件 84 private long ms; 85 public void onSuccess(int statusCode, Header[] headers, File file) { 86 System.out.println(Thread.currentThread().getName() + ": " + file + " 下载完成"); 87 checkOtherThread(); // 检查其他线程是否下载完毕, 如果都完了, 合并文件 88 } 89 public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) { 90 } 91 public void onProgress(int bytesWritten, int totalSize) { // 运行频率非常高 92 if (System.currentTimeMillis() - ms > 100) { 93 ms = System.currentTimeMillis(); 94 updateProgress(); 95 } 96 } 97 }; 98 handlerList.add(fileHandler); 99 100 AsyncHttpClient client = new AsyncHttpClient();101 client.addHeader("Range", "bytes=" + begin + "-" + end); // 设置请求数据的范围102 client.get(targetUrl, fileHandler);103 }104 }105 106 private void updateProgress() {107 long finishLength = getFinishLength();108 if (finishLength == 0)109 return;110 downloadPB.setProgress((int) finishLength);111 percentTV.setText(finishLength * 1000 / contentLength / 10f + "%"); 112 progressTV.setText(finishLength + "/" + contentLength);113 }114 115 private long getFinishLength() {116 long finishLength = 0;117 for (File cacheFile : cacheList) // 遍历所有临时文件118 finishLength += cacheFile.length(); // 统计总长度119 return finishLength;120 }121 122 private void checkOtherThread() {123 if (getFinishLength() == contentLength) { // 如果文件长度和ContentLength相等, 代表下载完成124 updateProgress();125 merge(); // 合并所有的临时文件126 }127 }128 129 private void merge() {130 try {131 FileOutputStream out = new FileOutputStream(localFile); 132 for (File cacheFile : cacheList) { // 遍历所有临时文件133 FileInputStream in = new FileInputStream(cacheFile); 134 byte[] buffer = new byte[8192];135 int length;136 while ((length = in.read(buffer)) != -1) // 读取每个文件137 out.write(buffer, 0, length); // 把每个文件的数据都写出到localFile138 in.close();139 cacheFile.delete();140 }141 out.close();142 } catch (IOException e) {143 throw new RuntimeException(e);144 }145 }146 147 public void stop() {148 for (MyFileHandler fileHandler : handlerList) {149 fileHandler.cancel();150 }151 }152 }
View Code

 

转载于:https://www.cnblogs.com/friends-wf/p/4528246.html

你可能感兴趣的文章
管理SELinux策略:优化故障排除及访问控制
查看>>
“互联网+”是云计算普及的助推器
查看>>
nuPSYS公司推出一款数据中心建模软件
查看>>
Oracle SQL Loader切身实例
查看>>
软件项目管理中的进度管理
查看>>
苹果野心很大 其实A系芯片已定制自主GPU
查看>>
张家港“互联网+大数据”精准管理风险
查看>>
同方国芯释疑问询 购台企不以定增为前提
查看>>
7月13日云栖精选夜读:什么才是这个时代最需要的BI人员? —— 阿里云MVP赵玮主题分享...
查看>>
大数据助力中国企业“走出去”
查看>>
Chrome OS 现可运行Android应用 仅限特定机型
查看>>
《黑客大曝光:移动应用安全揭秘及防护措施》一第3章 iOS系统
查看>>
为什么你应该在你下个 Ruby APP 中使用 Neo4j
查看>>
安卓手机曝彩信安全漏洞,因开源机制?
查看>>
《数据结构与算法 C语言版》—— 1.2数据结构的发展概况
查看>>
《贝叶斯思维:统计建模的Python学习法》——2.4 Monty Hall难题
查看>>
《ANTLR 4权威指南》——第1章 初识ANTLR 1.1 安装ANTLR
查看>>
[评论]究竟什么才是自主研发和自主知识产权?
查看>>
老是背锅的 CISO 如何回答 CEO 提出的高难度问题?
查看>>
《R语言与数据挖掘最佳实践和经典案例》—— 第1章 简  介
查看>>