zoukankan      html  css  js  c++  java
  • HttpURLConnection断点下载

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.RandomAccessFile;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import android.app.Activity;
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.ProgressBar;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
       private EditText      etPath;
       private EditText      etThread;
       private LinearLayout  llContent;
       int                   threadCount = 3;
       private String  path;
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          etPath = (EditText) findViewById(R.id.et_path);
          etThread = (EditText) findViewById(R.id.et_thread);
          llContent = (LinearLayout) findViewById(R.id.ll_content);
       }
    
       public void download(View v) {
          path = etPath.getText().toString().trim();
          String count = etThread.getText().toString().trim();
          if (TextUtils.isEmpty(path) || !path.startsWith("http")) {
             Toast.makeText(this, "请输入正确的网址,否则,兄弟我没法干活。。。", 0).show();
             return;
          }
    
          if (!TextUtils.isEmpty(count)) {
             threadCount = Integer.valueOf(count);
          }
    
          // 移除所有的view
          llContent.removeAllViews();
          // 有多少个线程,就加载多少个进度条
          for (int i = 0; i < threadCount; i++) {
             ProgressBar pb = (ProgressBar) View.inflate(this,
                    R.layout.progressbar, null);
             llContent.addView(pb);
          }
          // 开启线程
          new Thread() {
             public void run() {
                requestNet4DownLoad();
             }
          }.start();
       }
    
       /**
        * 下载
        */
       private void requestNet4DownLoad() {
          try {
             // 1. 在客户端创建和服务器资源一样大小的空文件
             URL url = new URL(path);
             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
             conn.setConnectTimeout(3000);
             conn.setRequestMethod("GET");
             int code = conn.getResponseCode();
             // 服务器资源文件的大小
             int fileLength = 0;
             if (code == 200) {
                fileLength = conn.getContentLength();
                System.out.println("文件大小:" + fileLength);
                // //可选,可以不写,检测硬盘的空间够不够用
                // RandomAccessFile raf = new RandomAccessFile(getFilePath(),
                // "rw");
                // //在硬盘上创建控件
                // raf.setLength(fileLength);
                // raf.close();
             }
             // 每个线程下载的区块大小
             int blockSize = fileLength / threadCount;
             // 2. 客户端开启多个线程去下载服务器的资源
             for (int threadId = 0; threadId < threadCount; threadId++) {
                int startIndex = threadId * blockSize;
                int endIndex = (threadId + 1) * blockSize - 1;
                // 最后一个线程,修正下载的结束位置
                if (threadId == threadCount - 1) {
                    endIndex = fileLength - 1;
                }
                // 开启线程
                new DownLoadThread(startIndex, endIndex, threadId).start();
             }
          } catch (Exception e) {
             e.printStackTrace();
          }
       }
    
        class DownLoadThread extends Thread {
          //开始位置
          int startIndex;
          //结束位置
          int endIndex;
          //线程ID
          int threadId;
          //断点的位置
          int lastDownPos;
          private ProgressBar   mPb;
          //最大的进度
          int maxProgress;
          //当前下载的进度
          int progress;
          //理论上开始下载的位置
          int fistIndex;
     
          public DownLoadThread(int startIndex, int endIndex, int threadId) {
             super();
             progress = startIndex;//初始化
             fistIndex = startIndex;
             this.startIndex = startIndex;
             this.endIndex = endIndex;
             this.threadId = threadId;
             lastDownPos = startIndex;//初始
             mPb = (ProgressBar) llContent.getChildAt(threadId);
             //设置最大的进度
             maxProgress = endIndex - startIndex;
             mPb.setMax(maxProgress);
          }
          @Override
          public void run() {
             super.run();
             System.out.println("理论上线程 : "+  threadId + " : "+ startIndex+" ~ "+endIndex)
             try {
                File tmpFile = new File(getFileTmpPath(threadId));
                if (tmpFile != null && tmpFile.exists() && tmpFile.length() > 0) {
                    FileInputStream fis = new FileInputStream(tmpFile);
                    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                    int  text = Integer.valueOf(br.readLine());
                    lastDownPos = text;//多次断点
                    startIndex = lastDownPos; //接受上一次断点的位置请求网络           
                    br.close();
                    System.out.println("断点后线程 : "+  threadId + " : "+ startIndex+" ~ "+endIndex);
                }          
                URL url = new URL(path);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(3000);
                //重要,设置请求的范围
    
                conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
    
                //部分请求成功 206
    
                int code = conn.getResponseCode();
                System.out.println(" code = "+code);
                if (code == 206) {
                    RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");
                    //重要,写文件之前定位
                    raf.seek(startIndex);              
                    //获取这个线程对应的一块资源
                    InputStream is = conn.getInputStream();
                    byte[] buffer = new byte[512];
                    int len = -1;             
                    while((len = is.read(buffer)) != -1){
                       //计算存储的位置
                       lastDownPos  += len;              
                      RandomAccessFile r = new RandomAccessFile(getFileTmpPath(threadId), "rwd");
    
                       String pos = String.valueOf(lastDownPos);
                       //存储断点的位置
                       r.write(pos.getBytes());
                       r.close();         
                       raf.write(buffer, 0, len);
                       //设置进度条的进度
                       progress = lastDownPos - fistIndex;
                       mPb.setProgress(progress);
                    }          
                   raf.close();
                }          
                // 3. 每个线程都下载完毕,整个资源就下载完了
                System.out.println("线程 "+threadId+" 干完活了!");
                //删除临时的进度文件
                System.out.println(tmpFile.delete());      
             } catch (Exception e) {
                e.printStackTrace();
             }
          }
       }
    
       /**
        * 获取文件的存储路径
        */
        String getFilePath(){
          int index = path.lastIndexOf("/")+1;
          return "/mnt/sdcard/"+path.substring(index);
       }
    
       **
        * 存储进度的临时文件
        */
    
        String getFileTmpPath(int threadId){
          return getFilePath()+threadId+".txt";
       }
    }
     
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    /**
     * 操作字符串
     */
    
    public class StringUtils {
       /**
        * 从流中转成字符串
        * 
        * @param is
        *            输入流
        * @return null表示失败
        */
    
       public static String parseStream2Str(InputStream is) {
          //内存输出流
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          int len = -1;
          byte[] buffer = new byte[1024*8];
          try {
             while((len = is.read(buffer)) != -1){
                baos.write(buffer, 0, len);
             }
             return new String(baos.toByteArray());
          } catch (Exception e) {
             e.printStackTrace();
             return null;
          }
       }
    }
    
  • 相关阅读:
    c++趣味之难以发现的bug
    解决html5 canvas 绘制字体、图片与图形模糊问题
    c++趣味之shared_ptr额外好处
    标准mysql(x64) Windows版安装过程
    解决Chrome与jQuery菜单兼容问题
    在Linux与Windows上获取当前堆栈信息
    TypeScript技巧集锦(陆续更新)
    c++趣味之变量名,颠覆所有教科书的VisualStudio
    Web前端:博客美化:三、右上角的Github Ribbon
    Web前端:博客美化:二、鼠标特效
  • 原文地址:https://www.cnblogs.com/loaderman/p/6432513.html
Copyright © 2011-2022 走看看