Vue.Js(html 5)+Java実装ファイルスライスアップロード

3351 ワード

説明
コードはプロジェクトから剥離して修正し、テストされず、構想だけを提供します.
フロントエンド
upload(file) {
  //               
  getIdx(md5)
    .then(function(res) {
      let retry = 3;
      uploadPart(retry, file, res.data);
    })
    .catch();  
}

uploadPart(retry, file, idx) {
  //      (  Byte)
  let bufferLength = 1024 * 1024 * 5;
  //        ,idx         ,           0
  let start = idx * bufferLength;
  //                
  if(start>=file.size || retry<=0) return;
  //       
  let end = start + bufferLength;
  //           ,     
  if (end > file.size) {end = fileSize;}
  //    
  var chunk = file.slice(start, end);
  //   formData        
  let formData = new FormData();
  formData.set("file", chunk);
  //        ,          
  if (start == 0) {  
    //        ,    
    let chunkNum = Math.ceil(file.size / bufferLength);
    formData.set("total", chunkNum);
  }
  //     api,    axios    
  doUpload(formData)
    //    ,      ,      
    .then(function() {
      retry = xx;//      
      uploadPart(retry, file, ++idx);
    })
    //    
    .catch(function() {
      retry--;//      
      //       
      uploadPart(retry, file, idx);
    });
},

ファイルスライスにアップロードされたフロントエンドのキーコードは1つだけです.
//    
var chunk = file.slice(start, end);

ファイルをsliceメソッドで切断し、ファイルアップロードのプロセスは、axiosを使用して要求を送信し、アップロードファイルブロックを再帰的に呼び出すビジネスおよび特定の技術によって異なります.注意しなければならないのは、Blob.slice(start,end)は、ファイルブロックにstartが指すバイトを含み、endが指すバイトを含まないので、使用時にBlobの境界に注意してください.
mozillaによるsliceの説明
バックエンド
/**         */
public static void doMergeFiles(String outFile, String[] files) {
    //      
    int BUFSIZE = 1024 * 1024;
    //  。           。
    Arrays.sort(files);
    //   
    FileChannel outChannel = null;
    //         
    String lastFlag = files[files.length-1];
    try {
        outChannel = new FileOutputStream(outFile).getChannel();
        //      
        for(String f : files){
            //               ,           md5   
            if(lastFlag.equals(f)){
                File last = new File(f);
                BUFSIZE = (int) last.length();//                
            }
            FileChannel fc = new FileInputStream(f).getChannel();
            // ByteBuffer    
            ByteBuffer bb = ByteBuffer.allocate(BUFSIZE);
            while(fc.read(bb) != -1){//       
                bb.flip();//    
                outChannel.write(bb);//    
                bb.clear();//    
            }
            fc.close();//   
        }
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } finally {
        try {if (outChannel != null) {outChannel.close();}} catch (IOException ignore) {}
    }
}

バックエンドのキーは、最後のファイルをアップロードした後にファイルのマージを行うファイルをマージすることです.ByteBufferキャッシュを使用し、FileChannelを使用してファイルの読み書きを行い、マージ操作を完了します.ファイルを保存する時、ファイル名は一致して、ファイルの接尾辞名はファイルのブロックの順序を取って、例えば第1ブロックのファイルは“xxx.01”で、第10ブロックは“xxx.10”で、注意して、桁数の前は“0”を補って、このように直接Arrayを使うことができます.sort()をソートします. パフォーマンスを向上させるために、キャッシュサイズを適切に設定できます.ファイルをアップロードしながらマージできます.ファイルがアップロードされるまでマージする必要はありません.
広がる
ここのファイルのアップロードは一度に1枚アップロードされ、アップロードに成功してから次の1枚アップロードが開始されます.フロントエンドがjavascriptではなく、マルチスレッドの使用をオンにすれば、同時にマルチファイルをアップロードしてアップロード速度を向上させることができます.アップロードされたファイルスライスはbitmapで格納され、ファイルをアップロードする前に、アップロードされたファイルスライスのbitmapデータをバックグラウンドから取得して解析し、アップロードされていないファイルスライスをマルチスレッドで処理する.