java源代码详细注释 网络文件下载之分段下载(可扩展 断点续传)

来源:互联网 发布:电子商务美工毕业论文 编辑:程序博客网 时间:2024/06/03 21:37

直接贴出代码





/*********************************************************************** * Module:  DownloadConnection.java * Author:  Administrator * Purpose: Defines the Class DownloadConnection ***********************************************************************/package com.tiny.httpdemo;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import lan.Log;/** * 这个下载连接类主要采用的方式是 将文件大小进行分块然后 并且有序下载   * 主要的目的是为了让一次下载的数量不要过于的大  以避免io阻塞 * 若要实现断点续传本程序的改进应该是很方便的   * 记住lastSize  既可以立马进行分解 * @author sada * */public class DownloadConnection  {//private static final String mtempurl = "http://219.138.125.22/myweb/mp3/CMP3/JH19.MP3";private static final String mtempurl = "http://file16.top100.cn/201105110911/AA5CC27CBE34DEB50A194581D1300881/Special_323149/%E8%8D%B7%E5%A1%98%E6%9C%88%E8%89%B2.mp3";public static void main(String[] args) {DownloadConnection dConnection = new DownloadConnection(mtempurl, 0);dConnection.download(mtempurl);}/** TAG */private static final String TAG = "Sada.DownloadConnection";/** 用于操作下载暂停,写本地文件时候跳出写循环的标志 */private boolean stop;/** 下载的文件的总长度 */private int totalSize;/** 如果是继续下载,lastSize表示上次已经下载的长度 */private int lastSize;/** 當前下載數據塊已下載數據大小,该变量会在写循环中增加*/private int currSize;/** 当前需要下载的文件大小,用于继续下载时,写循环的结束标志 */private int contentLength;/** 最大塊大小1MB */private static final int MAX_SIZE_ONE_MEGA = 1024 * 1024;private int lastloadsize = 0;    //已传的偏移private int currloadsize = 0;    //还要传得偏移private int contentlength = 0;   //总共要传得大小private int pogresslength = 0;   //进度条显示private static byte[] buffer;private int currentPercentage = 0;private RandomAccessFile raf;private File temp;private InputStream is; // 从网络读输入流/*---------------------------------*//** 连接实例 */protected HttpURLConnection conn;/** 连接的完整url */protected String url;/** 响应行的响应码,例如:404, 200, 500, 201等 */protected int responseCode;/** 响应行的响应消息关键字,例如:OK,Created,Unauthorized等 */protected String responseMessage;protected int timeout = -1;/** 文件名*/private String filename = ""; /** 准备请求行 */protected void prepareRequestLine() throws Exception{conn.setRequestMethod("GET");}/** 准备消息头 */protected void prepareHeaders() {int startfilesize = lastloadsize;      //当前文件偏移位置int endfilesize = currloadsize - 1;      //目的文件偏移位置conn.setAllowUserInteraction(true);  // 设置传输位置conn.setRequestProperty("RANGE", "bytes=" + startfilesize + "-" + endfilesize);Log.i(TAG,"(start = " + startfilesize + ")" + " - " + "(end = " + endfilesize + ")");}public void download(String surl){try{int totalsize = 0;  //整理后的文件大小URL mUrl = new URL(url);conn = (HttpURLConnection) mUrl.openConnection();// ---------------- 改进totalsize = conn.getContentLength() - this.lastSize;// 本次续下载的大小this.totalSize = conn.getContentLength();pogresslength = this.lastSize;  //初始化起始的进度偏移位置  在断点时用到conn.disconnect();Log.e(TAG, "the file size = " + this.totalSize);filename = getFileNameFromUrl(surl);File cache = new File("D:\\TEMP");if(cache != null && !cache.exists()){cache.mkdirs();}temp = new File("D:\\TEMP" + "\\" + filename);raf = new RandomAccessFile(temp, "rw");raf.seek(raf.length());int offset = 0; // 上次下载的位置for(int i = 0 ; i < totalsize / MAX_SIZE_ONE_MEGA ; i++){lastloadsize = offset;  //已传偏移currloadsize = lastloadsize + MAX_SIZE_ONE_MEGA;  // 将传到的偏移位置contentlength = currloadsize - lastloadsize;   // 总共要传的大小Log.v(TAG, "the size long " + contentlength);connect();if(stop){// 暂停下载数据//写数据库  pogresslength已下载长度return;}offset += MAX_SIZE_ONE_MEGA; }if(totalsize % MAX_SIZE_ONE_MEGA > 0){totalsize = totalsize % MAX_SIZE_ONE_MEGA;lastloadsize = offset;  //已传偏移currloadsize = lastloadsize + totalsize;  //将传到的偏移位置contentlength = currloadsize - lastloadsize;   //总共要传得大小Log.v(TAG, "the size long " + contentlength);if(contentlength > 0){  // 当下载最后大小为0时 直接做后面的操作connect();}if(stop){//写数据库  pogresslengthreturn;}}Log.v(TAG, "Download file success!\t\n" + "Size: " + lastloadsize + " bytes.");Log.v(TAG,"lastsize = " + pogresslength);Log.v(TAG,"fileSize = " + this.totalSize);// 更新下载进度到数据库File temp = new File("D:\\TEMP" + "\\" + filename);if(temp != null && temp.exists() && temp.length() != this.totalSize){ // 大小不一致则删除临时文件throw new Exception("The temp file is not completed!");}}catch(Exception e){}finally{if(raf != null){try {raf.close();raf = null;} catch (IOException e) {}}if(conn != null){conn.disconnect();conn = null;}if(is != null){try {is.close();} catch (IOException e) {}is = null;}System.gc();}}public void connect() throws Exception {URL mUrl = new URL(url);conn = (HttpURLConnection) mUrl.openConnection();conn.setDoInput(true);// 2.准备请求行prepareRequestLine();// 3.再准备消息头prepareHeaders();conn.setDoOutput(false);conn.connect();responseCode = conn.getResponseCode();responseMessage = conn.getResponseMessage();Log.d(TAG, "Response:" + responseCode + "  " + responseMessage);if(responseCode == 206 && "Partial Content".equals(responseMessage)){contentLength = conn.getContentLength();//Log.d(TAG, "the size long=" + contentLength);is = conn.getInputStream();if(!temp.exists() && pogresslength != 0){// 失败重新开始throw new Exception("The temp file has bean deleted");}currSize = 0;int ch = -1;// 恰好写完while(currSize < contentlength){// 判断是否暂停的标志if(stop){break;}ch = is.read(buffer);if(ch == -1){break;}raf.write(buffer, 0 , ch);currSize += ch;pogresslength = lastloadsize + currSize;if(currSize == contentlength){break;}}//下载进度更新Log.d(TAG, "Download block:\t" + currSize + " bytes.    " + contentLength);currSize = 0;is.close();conn.disconnect();conn = null;}else{conn.disconnect();if(conn != null){conn = null;}throw new Exception("Response header is incorrect!Must be: HTTP/1.1 206 Partial Content." + "code = " + responseCode + "   message = " +  responseMessage);}}/** 暂停下载 */public void pauseDownload() {Log.e(TAG,"I have done break Download!");stop = true;}/** 取消下载   先将下载线程暂停 然后将本地文件删除*/public void cancelDownload() {Log.e(TAG,"I have done cancel Download!");stop = true;}/** 状态改变 *  这里主要指下载的进度改变监听 */public void onStatusChanged() {long percentage = pogresslength  * 100L / totalSize;//Log.d(TAG, "Downloading percentage 2B: " + percentage);if(percentage > 0){if(percentage > currentPercentage){currentPercentage = (int) percentage;// 更新进度条Log.d(TAG, "Downloading percentage: " + currentPercentage + " %(" + filename + ").");}}}public void setTimeout(int timeout){this.timeout = timeout;}/** @param url * 构造方法,传入下载文件的blob url 和下载任务对应的download bean*/public DownloadConnection(String url, int continuteSize) {if(!url.startsWith("http://") && !url.startsWith("https://")){url = "http://" + url;}this.url = url;lastSize = continuteSize;if(buffer == null){buffer = new byte[8 * 1024];}}public void setUrl(String mUrl){url = mUrl;}public String getUrl(){return url;}/** * 依据URL获取文件名当为空时 设置文件名为 default.temp * @param url * @return */private static String getFileNameFromUrl(String url){if(url == null){ // 1url = "default.temp";}else {if(url.lastIndexOf("/") != -1){url = url.substring(url.lastIndexOf("/") + 1, url.length());if(isReg(url)){ // 若有非法字符存在则if(url.lastIndexOf(".") != -1){url = url.substring(url.lastIndexOf(".") + 1, url.length());url = "temp." + url;}else {url = "default.temp";}}}else {if(url.lastIndexOf(".") != -1){url = url.substring(url.lastIndexOf(".") + 1, url.length());url = "temp." + url;}else {url = "default.temp";}}}System.out.println("the file name is " + url);return url;}public static boolean isReg(String code){if(code.contains("/")){return false;}if(code.contains("\\")){ return false;}if(code.contains("[")){return false;}if(code.contains("]")){return false;}if(code.contains("?")){return false;}if(code.contains("<")){return false;}if(code.contains(">")){return false;}if(code.contains("*")){return false;}if(code.contains(":")){return false;}if(code.contains("|")){return false;}if(code.contains("\"")){return false;}return true;}}



转载请注明出处:http://community.csdn.net/




原创粉丝点击