ここにはバックエンドコードのみが記述されています。基本的な考え方は、フロントエンドがファイルをフラグメント化し、アップロードインターフェースにアクセスするたびに、現在のファイル数とフラグメントの総数などのパラメーターをバックエンドに渡します。
すぐ下にコードを貼り付けましょう難しいコードのほとんどはコメントされています:
ファイルエンティティクラスをアップロード:
エンティティークラスには、実用的な属性だけでなく、必要な関数がすでにたくさんあることがわかります。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