HTTP文件斷點上傳


         由於業務需要,手機需要采用http方式傳輸文件到后台WEB服務器,1、2百K的小文件不會有太大問題,幾M甚至幾百M的文件就很容易傳輸失敗。所以考慮實現HTTP文件斷點續傳功能,基本流程如下:

 

1.客戶端計算本地要上傳的文件的hashcode

2.根據指定的塊大小和文件大小計算最終的塊數

3.發送文件信息到服務器包括要上傳的文件名、大小、類型、塊數、Hashcode

4.服務器根據hashcode查詢服務器上是否已經存在對應的文件,以及文件的上傳狀態(上傳是否完成、是否組裝完成、已經上傳了哪些塊)

5.6.已經上傳完成的讀取文件URL地址返回給客戶端

7.8.未上傳完成的返回已經上傳的塊編號

9.客戶端根據返回值判斷,如果未上傳完成則從本地文件中讀取未上傳完成的塊內容

10.使用HTTP方式上傳到服務器

11.記錄已經上傳完成的塊到數據庫

12.檢查整個文件是否已經上傳完成

13.未完成則返回已經上傳的塊編號到客戶端讓它繼續上傳

14.上傳完成則進行塊文件合並過程,將其合並成目標文件

15.合並完成后返回目標文件的URL地址

 首先是數據庫表格:

create  table tb_fileupload(
fseq  int  primary  key auto_increment, #自增序列
fusername  varchar( 50),   #上傳者
fhashcode  varchar( 100),  #hash碼
fsize  int, #文件大小
fblocks  int, #塊數
ftype  varchar( 50),  #文件類型 
fready  varchar( 1024),  #已上傳完成的塊編號
finerpath  varchar( 200), #內部存儲路徑
fouterpath  varchar( 200), #外部存儲路徑
fisfinished  int  default  0,  #要否上傳完成
ftime  datetime #創建時間
)

 

 

接下來是客戶端代碼:

import java.io.FileInputStream;

public  class Auth{

   public  static  byte[] create(String filename)    throws Excepiton{
  InputStream fis =  new FileInputStream(filename);
   byte[] buf=  new  byte[1024];
  MessageDigest com=MessageDigest.getInstance("MD5");
   int num;
   do{
   num=fis.read(buf);
    if(num>0){
     com.update(buf,0,num);
   }
  } while(num!=-1)

  fis.close();
   return com.digest();
  }

   public  static String getMD5(String filename)  throw Exception {
     byte[] b =create(filename);
    String result=""; 
     for( int i=0;i<b.length;i++){
     result+=Integer.toString( (b[i]&0xff)+0x100,16).substring(1);
    }
     return result;
  }

}

 

 服務器端代碼包括以下幾部分:

1.新增要上傳的文件信息。

2.接收文件的各個塊。

3.合並塊。

 1:

private FileService fileSer

public  void saveFileInfo(){
   //先從數據庫中根據hashcode查找

   FileInfo info= fileSer.getFileByHash(hashcode);
   if(info==null){}

     //找不到則新增文件信息

     fileSer.saveFileInfo(username,filename,filesize,hashcode,blocks,filetype);

     return "added";

   }

   if(info.fisfinished){

     //如果已經上傳完畢則返回外部訪問路徑

     return info.fouterpath;

   }

   else{

     //未上傳完畢則返回已經上傳的塊

     return info.fready;

   }

)

 

 2:

private File block;

publicvoid saveblock(){

  if([這里驗證與塊一起上傳的block信息]){
     return "error";
  }

  FileInfo info= fileSer.getFileByHash(hashcode);

  if(info!=null){

    if(info.fisfinished){

     //如果已經上傳完畢則返回外部訪問路徑

     return info.fouterpath;

    }
    FileInputStream inStream = new FileInputStream(block);

    FileOutputStream outStream = new FileOutputStream(block存儲路徑+hashcode+block編號);

    int len=-1;

    byte[]buff= new byte[1024];

    while((len=inStream.read(buff))!=-1){

      outStream.write(buff,0,len);

    }

    outStream.flush();

    outStream.close();

    //更新數據庫中已經上傳的blocks信息

    fileSer.updateBlocks(hashcode,num);

    //進行合並檢查

    return union();

  }

}

 3:

 

public String uion(){
  int num =info.getFblocks();

   if(info.fisfinished){
    return info.fouterpah();

   }

   //這里要檢查下上傳的塊數量是否與num一致

  try{

    FileOutputStream outStream = new FileOutputStream(文件存儲路徑+info.ffilename);

    File inputfile=null;

     for(int i=1;i<num;i++){

      inputfile = new File(block存儲路徑+info.fhashcode+i);

      FileInputStream inStream = new FileInputStream(inputfile);

      int len=-1;

      byte[]buff = new byte[1024];

      while((len=inStream.read(buff))!=-1){

       outStream.write(buff,0,len);

      }

      outStream.flush();

      inStream.close();

      inputfile.delete();

     }

     outStream.close();

  }catch(Excption ex){

     return info.fblocks();

  }

   fileSer.updateouterpath(文件存儲路徑+info.ffilename,info.fhashcode);

   fileSer.updateFisfinished(true,info.fhashcode);

   return 文件存儲路徑+info.ffilename;

}

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM