JavaScriptの大きなファイルのアップロードソリューション

ここにはバックエンドコードのみが記述されています。基本的な考え方は、フロントエンドがファイルをフラグメント化し、アップロードインターフェースにアクセスするたびに、現在のファイル数とフラグメントの総数などのパラメーターをバックエンドに渡します。

すぐ下にコードを貼り付けましょう難しいコードのほとんどはコメントされています:

ファイルエンティティクラスをアップロード:

エンティティークラスには、実用的な属性だけでなく、必要な関数がすでにたくさんあることがわかります。MD5秒で送信される情報など。

パブリッククラスFileInf {

 

     パブリックFileInf(){}

     public String id = "";

     public String pid = "";

    public String pidRoot = "";   

     / ** *現在のアイテムがフォルダアイテムかどうかを示します。* /

     public boolean fdTask = false;        

     // ///それはフォルダ内のサブファイルですか/// </ summary>

     public boolean fdChild = false;

     / ** *ユーザーID。サードパーティのシステムと統合します。* /

     public int uid = 0;

     / ** *ローカルコンピュータ上のファイルの名前* /

     public String nameLoc = "";

     / ** *サーバー内のファイルの名前。* /

     public String nameSvr = "";

     / ** *ローカルコンピュータ上のファイルの完全パス。例:D:\ Soft \ QQ2012.exe * /

     public String pathLoc = "";  

     / ** *サーバー内のファイルの完全パス。例:F:\\ ftp \\ uer \\ md5.exe * /

     public String pathSvr = "";

     / ** *サーバー内のファイルの相対パス。例:/www/web/upload/md5.exe * /

     public String pathRel = "";

     / ** *ファイルMD5 * /

     public String md5 = "";

     / ** *デジタル化されたファイルの長さ。バイト単位の例:120125 * /

     public long lenLoc = 0;

     / ** *フォーマットされたファイルサイズ。例:10.03MB * /

     public String sizeLoc = "";

     / ** *再開するファイルの場所。* /

     public long offset = 0;

     / ** *アップロードされたサイズ。バイト単位* /

     public long lenSvr = 0;

     / ** *アップロードされた割合。例:10%* /

     public String perSvr = "0%";

     public boolean complete = false;

     public Date PostedTime = new Date();

     public boolean deleted = false;

     / ** *スキャンされたかどうかに関係なく、大きなフォルダーで使用するために提供され、大きなフォルダーがアップロードされた後にスキャンが開始されます。* /

     public boolean scaned = false;

}

 

1つ目は、ファイルデータ受信ロジックです。これは、コントロールによってアップロードされたファイルブロックデータを受信し、それをサーバーファイルに書き込みます。コントロールは、ブロックのインデックス、サイズ、MD5、および長さの情報を提供しており、ニーズに応じて柔軟に処理でき、ファイルブロックのデータを分散ストレージシステムに保存することもできます。

<%

out.clear();

文字列uid = request.getHeader( "uid"); //

文字列id = request.getHeader( "id");

文字列lenSvr = request.getHeader( "lenSvr");

文字列lenLoc = request.getHeader( "lenLoc");

文字列blockOffset = request.getHeader( "blockOffset");

String blockSize = request.getHeader( "blockSize");

String blockIndex = request.getHeader( "blockIndex");

文字列blockMd5 = request.getHeader( "blockMd5");

String complete = request.getHeader( "complete");

文字列pathSvr = "";

 

//パラメータは空です

if(StringUtils.isBlank(uid)

     || StringUtils.isBlank(id)

     || StringUtils.isBlank(blockOffset))

{

     XDebug.Output( "param is null");

     戻る;

}

 

//ファイルのアップロードリクエストがあることを確認します

ブールisMultipart = ServletFileUpload.isMultipartContent(request);

FileItemFactoryファクトリ=新しいDiskFileItemFactory();  

ServletFileUpload upload = new ServletFileUpload(factory);

リストファイル= null;

試す

{

     ファイル= upload.parseRequest(request);

}

キャッチ(FileUploadException e)

{//ファイルデータの解析エラー 

    out.println( "read file data error:" + e.toString());

    戻る;

  

}

 

FileItem rangeFile = null;

//アップロードされたすべてのファイルを取得します

イテレーターfileItr = files.iterator();

//すべてのファイルをループします

while(fileItr.hasNext())

{

     //現在のファイルを取得します

     rangeFile =(FileItem)fileItr.next();

     if(StringUtils.equals(rangeFile.getFieldName()、 "pathSvr"))

     {

         pathSvr = rangeFile.getString();

         pathSvr = PathTool.url_decode(pathSvr);

     }

}

 

boolean verify = false;

文字列msg = "";

文字列md5Svr = "";

long blockSizeSvr = rangeFile.getSize();

if(!StringUtils.isBlank(blockMd5))

{

     md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream());

}

 

verify = Integer.parseInt(blockSize)== blockSizeSvr;

if(!verify)

{

     msg = "ブロックサイズエラーsizeSvr:" + blockSizeSvr + "sizeLoc:" + blockSize;

}

 

if(verify &&!StringUtils.isBlank(blockMd5))

{

     検証= md5Svr.equals(blockMd5);

     if(!verify)msg = "block md5 error";

}

 

if(確認)

{

     //ファイルブロックデータを保存します

     FileBlockWriter res = new FileBlockWriter();

     //最初のブロックのみが作成されます

     if(Integer.parseInt(blockIndex)== 1)res.CreateFile(pathSvr、Long.parseLong(lenLoc));

     res.write(Long.parseLong(blockOffset)、pathSvr、rangeFile);

     up6_biz_event.file_post_block(id、Integer.parseInt(blockIndex));

    

     JSONObject o = new JSONObject();

     o.put( "msg"、 "ok");

     o.put( "md5"、md5Svr); 

     o.put( "offset"、blockOffset); //ファイルベースのブロックオフセット位置

     msg = o.toString();

}

rangeFile.delete();

out.write(msg);

%>

 

ファイル初期化セクション

<%

out.clear();

WebBase web = new WebBase(pageContext);

文字列id = web.queryString( "id");

文字列md5 = web.queryString( "md5");

文字列uid = web.queryString( "uid");

String lenLoc = web.queryString( "lenLoc"); //デジタル化されたファイルサイズ。12021

String sizeLoc = web.queryString( "sizeLoc"); //フォーマットされたファイルサイズ。10MB

文字列コールバック= web.queryString( "callback");

文字列pathLoc = web.queryString( "pathLoc");

pathLoc = PathTool.url_decode(pathLoc);

 

//パラメータは空です

if(StringUtils.isBlank(md5)

     && StringUtils.isBlank(uid)

     &StringUtils.isBlank(sizeLoc))

{

     out.write(callback + "({\" value \ ":null})");

     戻る;

}

 

FileInf fileSvr = new FileInf();

fileSvr.id = id;

fileSvr.fdChild = false;

fileSvr.uid = Integer.parseInt(uid);

fileSvr.nameLoc = PathTool.getName(pathLoc);

fileSvr.pathLoc = pathLoc;

fileSvr.lenLoc = Long.parseLong(lenLoc);

fileSvr.sizeLoc = sizeLoc;

fileSvr.deleted = false;

fileSvr.md5 = md5;

fileSvr.nameSvr = fileSvr.nameLoc;

 

//すべての単一ファイルはuuid / fileに保存されます

PathBuilderUuid pb = new PathBuilderUuid();

fileSvr.pathSvr = pb.genFile(fileSvr.uid、fileSvr);

fileSvr.pathSvr = fileSvr.pathSvr.replace( "\\"、 "/");

 

DBConfig cfg = new DBConfig();

DBFile db = cfg.db();

FileInf fileExist = new FileInf();

    

ブール型存在= db.exist_file(md5、fileExist);

//同じファイルがデータベースにすでに存在し、アップロードの進行状況があるため、この情報を直接使用します

if(exist && fileExist.lenSvr> 1)

{

     fileSvr.nameSvr = fileExist.nameSvr;

     fileSvr.pathSvr = fileExist.pathSvr;

     fileSvr.perSvr = fileExist.perSvr;

     fileSvr.lenSvr = fileExist.lenSvr;

     fileSvr.complete = fileExist.complete;

     db.Add(fileSvr);

    

     //トリガーイベント

    up6_biz_event.file_create_same(fileSvr);

} //このファイルは存在しません

そうしないと

{

     db.Add(fileSvr);

     //トリガーイベント

    up6_biz_event.file_create(fileSvr);

    

     FileBlockWriter fr = new FileBlockWriter();

     fr.CreateFile(fileSvr.pathSvr、fileSvr.lenLoc);

}

 

Gson gson =新しいGson();

文字列json = gson.toJson(fileSvr);

 

json = URLEncoder.encode(json、 "UTF-8"); //中国語の文字化けを防ぐためのエンコード

json = json.replace( "+"、 "%20");

json = callback + "({\" value \ ":\" "+ json +" \ "})"; // jsonp形式のデータを返します。

out.write(json);%>

 

最初のステップ:RandomAccessFile、ランダムアクセスファイルクラスオブジェクトを取得する

2番目のステップ:RandomAccessFileのgetChannel()メソッドを呼び出して、ファイルチャネルFileChannelを開きます。このロジックは最適化できます。将来、分散ストレージが必要になった場合は、分散ストレージに変更して、単一サーバーの負荷を軽減できます。

パブリッククラスFileBlockWriter {  

     public FileBlockWriter(){} 

     public void CreateFile(String pathSvr、long lenLoc)

     {

         試す

         {

              ファイルps = new File(pathSvr);

              PathTool.createDirectory(ps.getParent());

             

             RandomAccessFile raf = new RandomAccessFile(pathSvr、 "rw");

             raf.setLength(lenLoc); //修正:ファイルを元のサイズで作成します

             raf.close();

 

         }キャッチ(IOException e){

              // TODO自動生成されたcatchブロック

              e.printStackTrace();

         }       

     }

    

     public void write(long offset、String pathSvr、FileItem block)

     {       

         試す

         {

              InputStreamストリーム= block.getInputStream();           

              byte [] data = new byte [(int)block.getSize()];

              stream.read(data);

              stream.close();            

             

              RandomAccessFile raf = new RandomAccessFile(pathSvr、 "rw");

              raf.seek(offset);

              raf.write(data);

              raf.close();

             

         }キャッチ(IOException e){

              // TODO自動生成されたcatchブロック

              e.printStackTrace();

         }

     }

}

ステップ3:現在のブロック数を取得し、ファイルの最後のオフセットを計算する

ステップ4:ファイルのバイト長を取得するために使用される、現在のファイルブロックのバイト配列を取得する

ステップ5:FileChannelクラスFile Channelのmap()メソッドを使用して、ダイレクトバイトバッファーMappedByteBufferを作成する

手順6:ブロックのバイト配列をバッファーの現在の位置にあるmappedByteBuffer.put(byte [] b);

ステップ7:バッファーを解放する

手順8:ファイルが完全にアップロードされたかどうかを確認する

 

フォルダーのスキャン

 

 

ストレージパス生成クラス

 

さて、これで終わりです。質問や批判があれば、コメントやプライベートメッセージをお待ちしています。私たちは一緒に成長し、一緒に学びます。

最後に、エフェクト画像を入れます

 

バックエンドコードロジックはほとんど同じで、現在MySQL、Oracle、SQLをサポートしています。使用する前に、データベースを構成する必要があります。私が書いたこの記事を参照できます。http//blog.ncmem.com/wordpress/2019/08/07/java巨大なファイルのアップロードとダウンロード

議論するためにグループに参加する歓迎:374992201

おすすめ

転載: www.cnblogs.com/songsu/p/12704752.html