1.プロジェクト研究
ブレークポイントのアップロードの問題を研究する必要があるからです。長い検索の末、ようやくより良いプロジェクトを見つけました。
GoogleCodeでは、コードを取得するのは非常に不便です。ホストを構成し、コードを再度githubにアップロードすることをお勧めします。
https://github.com/freewebsys/java-large-file-uploader-demo
効果:
アップロード中、進行状況、時間、および割合が表示されます。
[一時停止]をクリックして一時停止し、[再開]をクリックして続行します。
2.コード分析
元のプロジェクト:
https://code.google.com/p/java-large-file-uploader/
このプロジェクトは2012年に最後に更新されました。プロジェクトはパッケージ化され、httpブレークポイントのアップロードを実現するための最も簡単な方法を使用しました。
HTML5にはファイル分割ファイルを読み取るためのクラスライブラリがあるため、ブレークポイントのアップロードをサポートできるため、これはHTML5がサポートするブラウザーでのみ表示できます。
同時に、ファイルブロックを検証するためにjsとjavaの両方でcr32が使用され、正しいデータアップロードが保証されます。
コードは最新のサーブレット3.0 APIを使用しており、非同期実行、監視、その他のメソッドを使用しています。
アップロードクラスUploadServlet
@Component( "javaLargeFileUploaderServlet")
@WebServlet(name = "javaLargeFileUploaderServlet"、urlPatterns = {"/ javaLargeFileUploaderServlet"})
パブリッククラスUploadServletはHttpRequestHandlerServletを拡張します
HttpRequestHandler {
プライベート静的最終ロガーログ= LoggerFactory.getLogger(UploadServlet.class);
@Autowired
UploadProcessor uploadProcessor;
@Autowired
FileUploaderHelper fileUploaderHelper;
@Autowired
ExceptionCodeMappingHelper exceptionCodeMappingHelper;
@Autowired
オーソライザーオーソライザー;
@Autowired
StaticStateIdentifierManager staticStateIdentifierManager;
@オーバーライド
public void handleRequest(HttpServletRequestリクエスト、HttpServletResponseレスポンス)
IOExceptionをスローします{
log.trace( "リクエストの処理");
シリアライズ可能なjsonObject = null;
{を試す
//リクエストからアクションを抽出します
UploadServletAction actionByParameterName =
UploadServletAction.valueOf(fileUploaderHelper.getParameterValue(request、UploadServletParameter.action));
//承認を確認
checkAuthorization(request、actionByParameterName);
//次に、要求されたアクションを処理します
jsonObject = processAction(actionByParameterName、request);
//応答に何かを書き込む必要がある場合
if(jsonObject!= null){
fileUploaderHelper.writeToResponse(jsonObject、response);
}
}
//例外であれば、それを書きます
キャッチ(例外e){
exceptionCodeMappingHelper.processException(e、response);
}
}
private void checkAuthorization(HttpServletRequest request、UploadServletAction actionByParameterName)
MissingParameterException、AuthorizationException {をスローします
//承認を確認
//進行しない場合(getの承認は本当に気にしないため)
//進行し、ファイルIDの配列を使用します)
if(!actionByParameterName.equals(UploadServletAction.getProgress)){
// uuidを抽出します
final String fileIdFieldValue = fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId、false);
//これがinitの場合、識別子はパラメータ内のIDです
UUID clientOrJobId;
文字列パラメーター= fileUploaderHelper.getParameterValue(request、UploadServletParameter.clientId、false);
if(actionByParameterName.equals(UploadServletAction.getConfig)&& parameter!= null){
clientOrJobId = UUID.fromString(parameter);
}
//そうでない場合は、マネージャーから取得します
そうしないと {
clientOrJobId = staticStateIdentifierManager.getIdentifier();
}
//オーソライザーを呼び出す
authorizer.getAuthorization(
リクエスト、
actionByParameterName、
clientOrJobId、
fileIdFieldValue!= null?getFileIdsFromString(fileIdFieldValue).toArray(new UUID [] {}):null);
}
}
Private Serializable processAction(UploadServletAction actionByParameterName、HttpServletRequest request)
例外をスローします{
log.debug( "処理アクション" + actionByParameterName.name());
シリアライズ可能なreturnObject = null;
スイッチ(actionByParameterName){
ケースgetConfig:
String parameterValue = fileUploaderHelper.getParameterValue(request、UploadServletParameter.clientId、false);
returnObject =
uploadProcessor.getConfig(
parameterValue!= null?UUID.fromString(parameterValue):null);
ブレーク;
ケースverifyCrcOfUncheckedPart:
returnObject = verifyCrcOfUncheckedPart(request);
ブレーク;
ケースprepareUpload:
returnObject = prepareUpload(request);
ブレーク;
ケースのclearFile:
uploadProcessor.clearFile(UUID.fromString(fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId)));
ブレーク;
ケースclearAll:
uploadProcessor.clearAll();
ブレーク;
ケースpauseFile:
List <UUID> uuids = getFileIdsFromString(fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId));
uploadProcessor.pauseFile(のUUID)。
ブレーク;
ケースresumeFile:
returnObject =
uploadProcessor.resumeFile(UUID.fromString(fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId)));
ブレーク;
ケースセットレート:
uploadProcessor.setUploadRate(UUID.fromString(fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId))、
Long.valueOf(fileUploaderHelper.getParameterValue(request、UploadServletParameter.rate)));
ブレーク;
ケースgetProgress:
returnObject = getProgress(request);
ブレーク;
}
return returnObject;
}
List <UUID> getFileIdsFromString(String fileIds){
String [] splittedFileIds = fileIds.split( "、");
List <UUID> uuids = Lists.newArrayList();
for(int i = 0; i <splittedFileIds.length; i ++){
uuids.add(UUID.fromString(splittedFileIds [i]));
}
uuidを返す;
}
プライベートシリアライズ可能なgetProgress(HttpServletRequest request)
MissingParameterExceptionをスローします{
シリアライズ可能なreturnObject;
String [] ids =
新しいgson()
.fromJson(fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId)、String []。class);
Collection <UUID> uuids = Collections2.transform(Arrays.asList(ids)、new Function <String、UUID>(){
@オーバーライド
public UUID apply(String input){
UUID.fromString(input);を返します。
}
});
returnObject = Maps.newHashMap();
(UUID fileId:uuids)の{
{を試す
ProgressJson progress = uploadProcessor.getProgress(fileId);
((HashMap <String、ProgressJson>)returnObject).put(fileId.toString()、progress);
}
キャッチ(FileNotFoundException e){
log.debug( "" + e.getMessage()); "+ fileId +"の進行状況は取得されません。
}
}
return returnObject;
}
プライベートシリアライズ可能なprepareUpload(HttpServletRequest request)
MissingParameterException、IOException {
//ファイル情報を抽出します
PrepareUploadJson [] fromJson =
新しいgson()
.fromJson(fileUploaderHelper.getParameterValue(request、UploadServletParameter.newFiles)、PrepareUploadJson []。class);
//それらを準備します
最終的なHashMap <String、UUID> prepareUpload = uploadProcessor.prepareUpload(fromJson);
//それらを返す
return Maps.newHashMap(Maps.transformValues(prepareUpload、new Function <UUID、String>(){
public String apply(UUID input){
input.toString();を返します。
};
}));
}
プライベートブールverifyCrcOfUncheckedPart(HttpServletRequest request)
IOException、MissingParameterException、FileCorruptedException、FileStillProcessingExceptionをスローします{
UUID fileId = UUID.fromString(fileUploaderHelper.getParameterValue(request、UploadServletParameter.fileId));
{を試す
uploadProcessor.verifyCrcOfUncheckedPart(fileId、
fileUploaderHelper.getParameterValue(request、UploadServletParameter.crc));
}
キャッチ(InvalidCrcException e){
//この例外をログに記録する必要はありません。フォールバック動作は
//スローメソッド。
//しかし、何かを返す必要があります!
Boolean.FALSE;を返します。
}
Boolean.TRUE;を返します。
}
}
非同期アップロードUploadServletAsync
@Component( "javaLargeFileUploaderAsyncServlet")
@WebServlet(name = "javaLargeFileUploaderAsyncServlet"、urlPatterns = {"/ javaLargeFileUploaderAsyncServlet"}、asyncSupported = true)
パブリッククラスUploadServletAsyncはHttpRequestHandlerServletを拡張します
HttpRequestHandler {
プライベート静的最終ロガーログ= LoggerFactory.getLogger(UploadServletAsync.class);
@Autowired
ExceptionCodeMappingHelper exceptionCodeMappingHelper;
@Autowired
UploadServletAsyncProcessor uploadServletAsyncProcessor;
@Autowired
StaticStateIdentifierManager staticStateIdentifierManager;
@Autowired
StaticStateManager <StaticStatePersistedOnFileSystemEntity> staticStateManager;
@Autowired
FileUploaderHelper fileUploaderHelper;
@Autowired
オーソライザーオーソライザー;
/ **
*ストリーミングリクエストにかかる最大時間。<br>
* /
プライベートの長いtaskTimeOut = DateUtils.MILLIS_PER_HOUR;
@オーバーライド
public void handleRequest(最終的なHttpServletRequestリクエスト、最終的なHttpServletResponseレスポンス)
ServletException、IOException {
//リクエストを処理します
{を試す
//アップロードが許可されているかどうかを確認します
if(!uploadServletAsyncProcessor.isEnabled()){
新しいUploadIsCurrentlyDisabled();をスローします。
}
//リクエストからコンテンツを抽出します
最終的なFileUploadConfigurationプロセス= fileUploaderHelper.extractFileUploadConfiguration(request);
log.debug( "受信したアップロード要求と構成:" + process);
//承認を確認します
最終的なUUID clientId = staticStateIdentifierManager.getIdentifier();
authorizer.getAuthorization(request、UploadServletAction.upload、clientId、process.getFileId());
//そのファイルが一時停止していないかどうかを確認します
if(uploadServletAsyncProcessor.isFilePaused(process.getFileId())){
log.debug( "ファイル" + process.getFileId()+ "は、非同期リクエストを無視して一時停止されています。");
戻る;
}
//モデルを取得します
StaticFileState fileState = staticStateManager.getEntityIfPresent()。getFileStates()。get(process.getFileId());
if(fileState == null){
新しいFileNotFoundException( "IDのファイル" + process.getFileId()+ "が見つかりません");
}
//リクエストを非同期に処理します
final AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(taskTimeOut);
//リスナーを追加してバケットをクリアし、プロセスが完了したときに入力ストリームを閉じます。
//と
//エラー
asyncContext.addListener(new UploadServletAsyncListenerAdapter(process.getFileId()){
@オーバーライド
void clean(){
log.debug( "request" + request + "completed。");
//ここで入力ストリームをクリアする必要はありません。
//プロセッサにそのたわごとをきれいにするように伝えます!
uploadServletAsyncProcessor.clean(clientId、process.getFileId());
}
});
//次に処理します
uploadServletAsyncProcessor.process(fileState、process.getFileId()、process.getCrc()、process.getInputStream()、
新しいWriteChunkCompletionListener(){
@オーバーライド
public void success(){
asyncContext.complete();
}
@オーバーライド
public void error(Exception exception){
//予期せず終了したストリームを処理します。これは、ユーザーが
//停止しました
//ストリーム
if(exception.getMessage()!= null){
if(exception.getMessage()。equals( "ストリームが予期せず終了しました")){
log.warn( "ユーザーはファイルのストリーミングを停止しました+ + process.getFileId());
}
else if(exception.getMessage()。equals( "ユーザーのキャンセル")){
log.warn( "ユーザーはファイルID" + process.getFileId());のストリーミングをキャンセルしました。
// 何もしない
}
そうしないと {
exceptionCodeMappingHelper.processException(exception、response);
}
}
そうしないと {
exceptionCodeMappingHelper.processException(exception、response);
}
asyncContext.complete();
}
});
}
キャッチ(例外e){
exceptionCodeMappingHelper.processException(e、response);
}
}
}
3.リクエストのフローチャート:
主なアイデアは、ファイルを分割してチャンクでアップロードすることです。
詳細な参照情報については、「up6 Large File Upload Control」をオンラインで検索できます。
議論するためにグループに参加する歓迎:374992201