zoukankan      html  css  js  c++  java
  • java多线程分块上传并支持断点续传最新修正完整版本[转]

    1. package com.test;  
    2.   
    3. import java.io.DataInputStream;  
    4. import java.io.DataOutputStream;  
    5. import java.io.File;  
    6. import java.io.FileInputStream;  
    7. import java.io.FileOutputStream;  
    8. import java.io.IOException;  
    9. import java.io.RandomAccessFile;  
    10. import java.net.HttpURLConnection;  
    11. import java.net.URL;  
    12. /** 
    13.  * 文件断点续传加分段上传线程 
    14.  * @author wzztestin 
    15.  * 
    16.  */  
    17. /** 
    18.  * 文件断点续传加分段上传线程 
    19.  * @author wzztestin 
    20.  * 
    21.  */  
    22. public class DownFileFetch extends Thread {  
    23.     DownFileInfoBean siteInfoBean = null; // 文件信息 Bean  
    24.     long[] nStartPos; // 开始位置  
    25.     long[] nEndPos; // 结束位置  
    26.     DownFileSplitterFetch[] fileSplitterFetch; // 子线程对象  
    27.     long nFileLength; // 文件长度  
    28.     boolean bFirst = true; // 是否第一次取文件  
    29.     boolean bStop = false; // 停止标志  
    30.     File tmpFile; // 文件下载的临时信息  
    31.     DataOutputStream output; // 输出到文件的输出流  
    32.     boolean fileflag; //是本地上传还是远程下载的标志  
    33.     File downfile; //本地文件下载  
    34.     int splitter = 0;  
    35.       
    36.     /** 
    37.      * 下载上传文件抓取初始化 
    38.      * @param bean 
    39.      * @throws IOException 
    40.      */  
    41.     public DownFileFetch(DownFileInfoBean bean) throws IOException {  
    42.         siteInfoBean = bean;  
    43.         /** 
    44.          * File.separator windows是\,unix是/ 
    45.          */  
    46.         tmpFile = new File(bean.getSFilePath() + File.separator  
    47.                 + bean.getSFileName() + ".info");  
    48.         if (tmpFile.exists()) {  
    49.             bFirst = false;  
    50.             //读取已下载的文件信息  
    51.             read_nPos();  
    52.         } else {  
    53.             nStartPos = new long[bean.getNSplitter()];  
    54.             nEndPos = new long[bean.getNSplitter()];  
    55.         }  
    56.         fileflag = bean.getFileflag();  
    57.         downfile = bean.getDownfile();  
    58.         this.splitter = bean.getNSplitter();  
    59.     }  
    60.   
    61.     public void run() {  
    62.         // 获得文件长度  
    63.         // 分割文件  
    64.         // 实例 FileSplitterFetch  
    65.         // 启动 FileSplitterFetch 线程  
    66.         // 等待子线程返回  
    67.         try {  
    68.             if (bFirst) {  
    69.                 nFileLength = getFileSize();  
    70.                 if (nFileLength == -1) {  
    71.                     DownFileUtility.log("File Length is not known!");  
    72.                 } else if (nFileLength == -2) {  
    73.                     DownFileUtility.log("File is not access!");  
    74.                 } else {  
    75.                     for (int i = 0; i < nStartPos.length; i++) {  
    76.                         nStartPos[i] = (long) (i * (nFileLength / nStartPos.length));  
    77.                     }  
    78.                     for (int i = 0; i < nEndPos.length - 1; i++) {  
    79.                         nEndPos[i] = nStartPos[i + 1];  
    80.                     }  
    81.                     nEndPos[nEndPos.length - 1] = nFileLength;  
    82.                 }  
    83.             }  
    84.             // 启动子线程  
    85.             fileSplitterFetch = new DownFileSplitterFetch[nStartPos.length];  
    86.             for (int i = 0; i < nStartPos.length; i++) {  
    87.                 fileSplitterFetch[i] = new DownFileSplitterFetch(  
    88.                         siteInfoBean.getSSiteURL(), siteInfoBean.getSFilePath()  
    89.                                 + File.separator + siteInfoBean.getSFileName()+"_"+i,  
    90.                         nStartPos[i], nEndPos[i], i,fileflag,downfile,bFirst);  
    91.                 DownFileUtility.log("Thread " + i + " , nStartPos = " + nStartPos[i]  
    92.                         + ", nEndPos = " + nEndPos[i]);  
    93.                 fileSplitterFetch[i].start();  
    94.             }  
    95.             //下载子线程是否完成标志  
    96.             boolean breakWhile = false;  
    97.             while (!bStop) {  
    98.                 write_nPos();  
    99.                 DownFileUtility.sleep(500);  
    100.                 breakWhile = true;  
    101.                 for (int i = 0; i < nStartPos.length; i++) {  
    102.                     if (!fileSplitterFetch[i].bDownOver) {  
    103.                         breakWhile = false;  
    104.                         break;  
    105.                     }else{  
    106.                         write_nPos();  
    107.                     }  
    108.                 }  
    109.                 if (breakWhile){  
    110.                     break;  
    111.                 }  
    112.             }  
    113.             hebinfile(siteInfoBean.getSFilePath()+ File.separator + siteInfoBean.getSFileName(),splitter);  
    114.             DownFileUtility.log("文件下载结束!");  
    115.         } catch (Exception e) {  
    116.             e.printStackTrace();  
    117.         }  
    118.     }  
    119.       
    120.     /** 
    121.      * 获得文件长度 
    122.      * @return 
    123.      */  
    124.     public long getFileSize() {  
    125.         int nFileLength = -1;  
    126.         if(fileflag){  
    127.             try {  
    128.                 URL url = new URL(siteInfoBean.getSSiteURL());  
    129.                 HttpURLConnection httpConnection = (HttpURLConnection) url  
    130.                         .openConnection();  
    131.                 httpConnection.setRequestProperty("User-Agent", "NetFox");  
    132.                 int responseCode = httpConnection.getResponseCode();  
    133.                 if (responseCode >= 400) {  
    134.                     processErrorCode(responseCode);  
    135.                     //represent access is error  
    136.                     return -2;   
    137.                 }  
    138.                 String sHeader;  
    139.                 for (int i = 1;; i++) {  
    140.                     sHeader = httpConnection.getHeaderFieldKey(i);  
    141.                     if (sHeader != null) {  
    142.                         if (sHeader.equals("Content-Length")) {  
    143.                             nFileLength = Integer.parseInt(httpConnection  
    144.                                     .getHeaderField(sHeader));  
    145.                             break;  
    146.                         }  
    147.                     } else {  
    148.                         break;  
    149.                     }  
    150.                 }  
    151.             } catch (IOException e) {  
    152.                 e.printStackTrace();  
    153.             } catch (Exception e) {  
    154.                 e.printStackTrace();  
    155.             }  
    156.             DownFileUtility.log(nFileLength);  
    157.         }else{  
    158.             try{  
    159.                 File myflie = downfile;  
    160.                 nFileLength = (int)myflie.length();  
    161.             }catch(Exception e){  
    162.                 e.printStackTrace();  
    163.             }  
    164.             DownFileUtility.log(nFileLength);  
    165.         }  
    166.         return nFileLength;  
    167.     }  
    168.   
    169.     /** 
    170.      * 保存下载信息(文件指针位置) 
    171.      */  
    172.     private void write_nPos() {  
    173.         try {  
    174.             output = new DataOutputStream(new FileOutputStream(tmpFile));  
    175.             output.writeInt(nStartPos.length);  
    176.             for (int i = 0; i < nStartPos.length; i++) {  
    177.                 output.writeLong(fileSplitterFetch[i].nStartPos);  
    178.                 output.writeLong(fileSplitterFetch[i].nEndPos);  
    179.             }  
    180.             output.close();  
    181.         } catch (IOException e) {  
    182.             e.printStackTrace();  
    183.         } catch (Exception e) {  
    184.             e.printStackTrace();  
    185.         }  
    186.     }  
    187.   
    188.     /** 
    189.      * 读取保存的下载信息(文件指针位置) 
    190.      */  
    191.     private void read_nPos() {  
    192.         try {  
    193.             DataInputStream input = new DataInputStream(new FileInputStream(  
    194.                     tmpFile));  
    195.             int nCount = input.readInt();  
    196.             nStartPos = new long[nCount];  
    197.             nEndPos = new long[nCount];  
    198.             for (int i = 0; i < nStartPos.length; i++) {  
    199.                 nStartPos[i] = input.readLong();  
    200.                 nEndPos[i] = input.readLong();  
    201.             }  
    202.             input.close();  
    203.         } catch (IOException e) {  
    204.             e.printStackTrace();  
    205.         } catch (Exception e) {  
    206.             e.printStackTrace();  
    207.         }  
    208.     }  
    209.       
    210.     /** 
    211.      * 输出错误信息 
    212.      * @param nErrorCode 
    213.      */  
    214.     private void processErrorCode(int nErrorCode) {  
    215.         DownFileUtility.log("Error Code : " + nErrorCode);  
    216.     }  
    217.   
    218.     /** 
    219.      * 停止文件下载 
    220.      */  
    221.     public void siteStop() {  
    222.         bStop = true;  
    223.         for (int i = 0; i < nStartPos.length; i++)  
    224.             fileSplitterFetch[i].splitterStop();  
    225.     }  
    226.       
    227.     /** 
    228.      * 合并文件 
    229.      * @param sName 
    230.      * @param splitternum 
    231.      */  
    232.     private void hebinfile(String sName,int splitternum){  
    233.         try{  
    234.             File file = new File(sName);  
    235.             if(file.exists()){  
    236.                 file.delete();  
    237.             }  
    238.             RandomAccessFile saveinput = new RandomAccessFile(sName,"rw");  
    239.             for(int i = 0;i<splitternum;i++){  
    240.                 try {  
    241.                     RandomAccessFile input = new RandomAccessFile (new File(sName+"_"+i),"r");  
    242.                     byte[] b = new byte[1024];  
    243.                     int nRead;  
    244.                     while ((nRead = input.read(b, 0, 1024)) > 0) {  
    245.                         write(saveinput,b, 0, nRead);  
    246.                     }  
    247.                     input.close();  
    248.                 } catch (Exception e) {  
    249.                     e.printStackTrace();  
    250.                 }  
    251.             }  
    252.             DownFileUtility.log("file size is "+saveinput.length());  
    253.         }catch(Exception e){  
    254.             e.printStackTrace();  
    255.         }  
    256.     }  
    257.       
    258.     /** 
    259.      * 写文件 
    260.      * @param b 
    261.      * @param nStart 
    262.      * @param nLen 
    263.      * @return 
    264.      */  
    265.     private int write(RandomAccessFile oSavedFile,byte[] b, int nStart, int nLen) {  
    266.         int n = -1;  
    267.         try {  
    268.             oSavedFile.seek(oSavedFile.length());  
    269.             oSavedFile.write(b, nStart, nLen);  
    270.             n = nLen;  
    271.         } catch (IOException e) {  
    272.             e.printStackTrace();  
    273.         }  
    274.         return n;  
    275.     }  
    276. }  
    Java代码  收藏代码
    1. package com.test;  
    2.   
    3. import java.io.File;  
    4. import java.io.IOException;  
    5. import java.io.InputStream;  
    6. import java.io.RandomAccessFile;  
    7. import java.net.HttpURLConnection;  
    8. import java.net.URL;  
    9. /** 
    10.  * 下载上传子线程 
    11.  * @author wzztestin 
    12.  * 
    13.  */  
    14. public class DownFileSplitterFetch extends Thread {  
    15.     String sURL; // 下载文件的地址  
    16.     long nStartPos; // 文件分段的开始位置  
    17.     long nEndPos; // 文件分段的结束位置  
    18.     int nThreadID; // 线程的 ID  
    19.     boolean bDownOver = false; // 是否下载完成  
    20.     boolean bStop = false; // 停止下载  
    21.     DownFileAccess fileAccessI = null; // 文件对象  
    22.     boolean fileflag; //是URL下载还是本地下载  
    23.     File file = null;//本地下载文件  
    24.     boolean bFirst = true;  
    25.       
    26.     /** 
    27.      * 下载,上传子线程初始化 
    28.      * @param sURL 
    29.      * @param sName 
    30.      * @param nStart 
    31.      * @param nEnd 
    32.      * @param id 
    33.      * @param fileflag 
    34.      * @param downfile 
    35.      * @throws IOException 
    36.      */  
    37.     public DownFileSplitterFetch(String sURL, String sName, long nStart, long nEnd,  
    38.             int id,boolean fileflag,File downfile,boolean bFirst) throws IOException {  
    39.         this.sURL = sURL;  
    40.         this.nStartPos = nStart;  
    41.         this.nEndPos = nEnd;  
    42.         nThreadID = id;  
    43.         fileAccessI = new DownFileAccess(sName, nStartPos,bFirst);  
    44.         this.fileflag = fileflag;  
    45.         this.file = downfile;  
    46.         this.bFirst = bFirst;  
    47.     }  
    48.       
    49.     /** 
    50.      * 线程执行 
    51.      */  
    52.     public void run() {  
    53.         if(fileflag){  
    54.             this.urldownload();  
    55.         }else{  
    56.             this.filedownload();  
    57.         }  
    58.     }  
    59.   
    60.     /** 
    61.      * 打印回应的头信息 
    62.      * @param con 
    63.      */  
    64.     public void logResponseHead(HttpURLConnection con) {  
    65.         for (int i = 1;; i++) {  
    66.             String header = con.getHeaderFieldKey(i);  
    67.             if (header != null){  
    68.                 DownFileUtility.log(header + " : " + con.getHeaderField(header));  
    69.             }else{  
    70.                 break;  
    71.             }  
    72.         }  
    73.     }  
    74.       
    75.     /** 
    76.      * 地址下载 
    77.      */  
    78.     private void urldownload(){  
    79.         DownFileUtility.log("Thread " + nThreadID + " url down filesize is "+(nEndPos-nStartPos));  
    80.         DownFileUtility.log("Thread " + nThreadID + " url start >> "+nStartPos +"------end >> "+nEndPos);  
    81.         while (nStartPos < nEndPos && !bStop) {  
    82.             try {  
    83.                 URL url = new URL(sURL);  
    84.                 HttpURLConnection httpConnection = (HttpURLConnection) url  
    85.                         .openConnection();  
    86.                 httpConnection.setRequestProperty("User-Agent", "NetFox");  
    87.                 String sProperty = "bytes=" + nStartPos + "-";  
    88.                 httpConnection.setRequestProperty("RANGE", sProperty);  
    89.                 DownFileUtility.log(sProperty);  
    90.                 InputStream input = httpConnection.getInputStream();  
    91.                 byte[] b = new byte[1024];  
    92.                 int nRead;  
    93.                 while ((nRead = input.read(b, 0, 1024)) > 0  
    94.                         && nStartPos < nEndPos && !bStop) {  
    95.                     if((nStartPos+nRead)>nEndPos)  
    96.                     {  
    97.                         nRead = (int)(nEndPos - nStartPos);  
    98.                     }  
    99.                     nStartPos += fileAccessI.write(b, 0, nRead);  
    100.                 }  
    101.                 DownFileUtility.log("Thread " + nThreadID + " nStartPos : "+nStartPos);  
    102.                 fileAccessI.oSavedFile.close();  
    103.                 DownFileUtility.log("Thread " + nThreadID + " is over!");  
    104.                 input.close();  
    105.                 bDownOver = true;  
    106.             } catch (Exception e) {  
    107.                 e.printStackTrace();  
    108.             }  
    109.         }  
    110.         if(!bDownOver){  
    111.             if(nStartPos >= nEndPos){  
    112.                 bDownOver = true;  
    113.             }  
    114.         }  
    115.     }  
    116.       
    117.     /** 
    118.      * 文件下载 
    119.      */  
    120.     private void filedownload(){  
    121.         DownFileUtility.log("Thread " + nThreadID + " down filesize is "+(nEndPos-nStartPos));  
    122.         DownFileUtility.log("Thread " + nThreadID + " start >> "+nStartPos +"------end >> "+nEndPos);  
    123.         while (nStartPos < nEndPos && !bStop) {  
    124.             try {  
    125.                 RandomAccessFile input = new RandomAccessFile(file,"r");  
    126.                 input.seek(nStartPos);  
    127.                 byte[] b = new byte[1024];  
    128.                 int nRead;  
    129.                 while ((nRead = input.read(b, 0, 1024)) > 0  
    130.                         && nStartPos < nEndPos && !bStop) {  
    131.                     if((nStartPos+nRead)>nEndPos)  
    132.                     {  
    133.                         nRead = (int)(nEndPos - nStartPos);  
    134.                     }  
    135.                     nStartPos += fileAccessI.write(b, 0, nRead);  
    136.                 }  
    137.                 fileAccessI.oSavedFile.close();  
    138.                 DownFileUtility.log("Thread " + nThreadID + " is over!");  
    139.                 input.close();  
    140.                 bDownOver = true;  
    141.                 input.close();  
    142.             } catch (Exception e) {  
    143.                 e.printStackTrace();  
    144.             }  
    145.         }  
    146.         if(!bDownOver){  
    147.             if(nStartPos >= nEndPos){  
    148.                 bDownOver = true;  
    149.             }  
    150.         }  
    151.         DownFileUtility.log("Thread " + nThreadID + "last start >> "+nStartPos );  
    152.     }  
    153.       
    154.     /** 
    155.      * 停止 
    156.      */  
    157.     public void splitterStop() {  
    158.         bStop = true;  
    159.     }  
    160. }  
    Java代码  收藏代码
    1. package com.test;  
    2.   
    3. import java.io.*;  
    4.   
    5. /** 
    6.  * 文件对象 
    7.  * @author wzztestin 
    8.  * 
    9.  */  
    10. public class DownFileAccess implements Serializable {  
    11.     /** 
    12.      *  
    13.      */  
    14.     private static final long serialVersionUID = -2518013155676212866L;  
    15.     //写入文件的流  
    16.     RandomAccessFile oSavedFile;  
    17.     //开始位置  
    18.     long nPos;  
    19.     boolean bFirst;  
    20.   
    21.     public DownFileAccess() throws IOException {  
    22.         this("", 0,true);  
    23.     }  
    24.       
    25.     /** 
    26.      * 写入文件初始化 
    27.      * @param sName 
    28.      * @param nPos 
    29.      * @throws IOException 
    30.      */  
    31.     public DownFileAccess(String sName, long nPos,boolean bFirst) throws IOException {  
    32.         File wfile = new File(sName);  
    33.         oSavedFile = new RandomAccessFile(wfile,"rw");  
    34.         if(!bFirst){  
    35.             oSavedFile.seek(wfile.length());  
    36.         }  
    37.         this.nPos = nPos;  
    38.         this.bFirst = bFirst;  
    39.     }  
    40.       
    41.     /** 
    42.      * 写文件 
    43.      * @param b 
    44.      * @param nStart 
    45.      * @param nLen 
    46.      * @return 
    47.      */  
    48.     public synchronized int write(byte[] b, int nStart, int nLen) {  
    49.         int n = -1;  
    50.         try {  
    51.             oSavedFile.write(b, nStart, nLen);  
    52.             n = nLen;  
    53.         } catch (IOException e) {  
    54.             e.printStackTrace();  
    55.         }  
    56.         return n;  
    57.     }  
    58. }  
    Java代码  收藏代码
    1. package com.test;  
    2.   
    3. import java.io.File;  
    4.   
    5. public class DownFileInfoBean {  
    6.     private String sSiteURL; // 文件的下载地址  
    7.     private String sFilePath; // 保存文件的路径  
    8.     private String sFileName; // 保存文件的名字  
    9.     private int nSplitter; // 文件分成几段,默认是5段  
    10.     private boolean fileflag; // 如果为FALSE则是本地下载,为TRUE则URL下载  
    11.     private File downfile;  
    12.   
    13.     public File getDownfile() {  
    14.         return downfile;  
    15.     }  
    16.   
    17.     public void setDownfile(File downfile) {  
    18.         this.downfile = downfile;  
    19.     }  
    20.   
    21.     public boolean getFileflag() {  
    22.         return fileflag;  
    23.     }  
    24.   
    25.     public void setFileflag(boolean fileflag) {  
    26.         this.fileflag = fileflag;  
    27.     }  
    28.       
    29.     /** 
    30.      * 默认初始化 
    31.      */  
    32.     public DownFileInfoBean() {  
    33.         // default 5  
    34.         this("", "", "", 5,false,null);  
    35.     }  
    36.       
    37.     /** 
    38.      * 下载文件信息初始化 
    39.      * @param sURL 下载的链接地址 
    40.      * @param sPath 上传的保存路径 
    41.      * @param sName 上传保存的文件名 
    42.      * @param nSpiltter 文件分段个数 
    43.      * @param fileflag 是本地文件上传下载还是链接上传下载的标志 
    44.      * @param downfile 本地下载文件(FILE) 
    45.      */  
    46.     public DownFileInfoBean(String sURL, String sPath, String sName, int nSpiltter,boolean fileflag,File downfile) {  
    47.         sSiteURL = sURL;  
    48.         sFilePath = sPath;  
    49.         sFileName = sName;  
    50.         this.nSplitter = nSpiltter;  
    51.         this.fileflag = fileflag;  
    52.         this.downfile = downfile;  
    53.     }  
    54.   
    55.     public String getSSiteURL() {  
    56.         return sSiteURL;  
    57.     }  
    58.   
    59.     public void setSSiteURL(String value) {  
    60.         sSiteURL = value;  
    61.     }  
    62.   
    63.     public String getSFilePath() {  
    64.         return sFilePath;  
    65.     }  
    66.   
    67.     public void setSFilePath(String value) {  
    68.         sFilePath = value;  
    69.     }  
    70.   
    71.     public String getSFileName() {  
    72.         return sFileName;  
    73.     }  
    74.   
    75.     public void setSFileName(String value) {  
    76.         sFileName = value;  
    77.     }  
    78.   
    79.     public int getNSplitter() {  
    80.         return nSplitter;  
    81.     }  
    82.   
    83.     public void setNSplitter(int nCount) {  
    84.         nSplitter = nCount;  
    85.     }  
    86. }  
    Java代码  收藏代码
    1. package com.test;  
    2.   
    3. /** 
    4.  * 简单的工具类 
    5.  * @author wzztestin 
    6.  * 
    7.  */  
    8. public class DownFileUtility {  
    9.     public DownFileUtility() {  
    10.     }  
    11.       
    12.     /** 
    13.      * 休眠时长 
    14.      * @param nSecond 
    15.      */  
    16.     public static void sleep(int nSecond) {  
    17.         try {  
    18.             Thread.sleep(nSecond);  
    19.         } catch (Exception e) {  
    20.             e.printStackTrace();  
    21.         }  
    22.     }  
    23.       
    24.     /** 
    25.      * 打印日志信息 
    26.      * @param sMsg 
    27.      */  
    28.     public static void log(String sMsg) {  
    29.         System.err.println(sMsg);  
    30.     }  
    31.       
    32.     /** 
    33.      * 打印日志信息 
    34.      * @param sMsg 
    35.      */  
    36.     public static void log(int sMsg) {  
    37.         System.err.println(sMsg);  
    38.     }  
    39. }  
    Java代码  收藏代码
    1. package com.test;  
    2.   
    3. public class TestMethod {  
    4.     public TestMethod() {  
    5.         try {  
    6.             DownFileInfoBean bean = new DownFileInfoBean(  
    7.                     "http://cdn.market.hiapk.com/data/upload//2012/09_27/17/car.wu.wei.kyo.shandian_174928.apk", "D:\temp",  
    8.                     "shandian_174928.apk", 5,true,null);  
    9.             /*File file = new File("D:\dan07.apk"); 
    10.             DownFileInfoBean bean = new DownFileInfoBean(null, "D:\temp", 
    11.                     "dan07.apk", 3,false,file);*/  
    12.             DownFileFetch fileFetch = new DownFileFetch(bean);  
    13.             fileFetch.start();  
    14.         } catch (Exception e) {  
    15.             e.printStackTrace();  
    16.         }  
    17.     }  
    18.   
    19.     public static void main(String[] args) {  
    20.         new TestMethod();  
    21.     }  
    22. }  
  • 相关阅读:
    记录一次在 VirtualBox的添加共享windows文件后,发现没有共享文件的事
    linux 压缩解压缩命令
    关于erlang中的timer:tc/3
    python基础:while循环,for循环
    grep和正则表达式参数
    grep和正则表达式
    nginx反向代理三台web
    安装nginx包
    部署samba
    samba了解
  • 原文地址:https://www.cnblogs.com/austinspark-jessylu/p/8745605.html
Copyright © 2011-2022 走看看