• java 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;

    }

  • 相关阅读:
    最值
    算数平均值/加权平均值
    jdbatemplate使用
    所有正规jar包
    java代码在计算机中经历的三个阶段,反射的原理
    lambda函数式编程思想
    重写equals方法
    安全牛-弱点扫描
    安全牛-主动收集
    安全牛-被动收集
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318259.html
Copyright © 2020-2023  润新知