リクエストの中止について
要領の大きいファイルを通信中に、処理を中止したい時があります。
通信処理を途中で中止する方法を試してみます。
通信処理中のHTTPリエクトを中止するには、abort()メソッドを呼び出して中止します。
abort()メソッドを呼び出すと、abortイベントが発生し、通信処理を停止します。
通信処理中のリクエストを中止する方法として、下記のようなHTMLを用意しました。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テストHTML</title> </head> <body> <form id="testform" enctype="multipart/form-data"> <div> <input type="file" name="file1" id="file1"> </div> <div> <label for="progress">進捗</label> <div id="percent"></div> <progress id="progress" value="0" max="100"></progress> </div> <div> <input type="button" id="sample_file_upload" value="ファイルアップロードのテスト"> </div> <div> <input type="button" id="stop_file_upload" value="ファイルアップロードの中止"> </div> </form> <div>通信時の処理内容</div> <div id="ajax_result"></div> <script type="text/javascript"> // ファイルアップロード中止ボタンのDOMを取得 let element_stop_file_upload = document.getElementById('stop_file_upload'); // ファイルアップロード中止ボタンを非表示にする element_stop_file_upload.style.display = 'none'; // ファイルアップロードボタンのDOMを取得 let element_sample_file_upload = document.getElementById('sample_file_upload'); element_sample_file_upload.addEventListener('click', SendXMLHttpRequest, false); // ボタン押下時の処理 function SendXMLHttpRequest() { // 通信処理を画面に出力する為、操作用DOMの取得 let result = document.getElementById("ajax_result"); result.innerHTML += 'ファイルアップロードのテスト start' + '<br />'; result.innerHTML += '通信処理の開始' + '<br />'; // フォーム内容の取得 let testform_data = document.getElementById("testform"); // 送信用データ let form_data = new FormData(testform_data); // 通信用XMLHttpRequestを生成 let req = new XMLHttpRequest(); // POST形式でサーバ側の「response.php」へデータ通信を行う req.open("POST", "response.php"); // ファイル通信時の進捗確認用にプログレスバーを更新する req.upload.addEventListener("progress", function(e) { if (e.lengthComputable) { // ファイルアップロード中止ボタンを表示する // document.getElementById('stop_file_upload').style.display = 'block'; element_stop_file_upload.style.display = 'block'; let progress_value = Math.round(e.loaded / e.total * 100); // 進捗%表示用に値を更新する document.getElementById('percent').innerHTML = progress_value + "%"; // プログレスバーの値にファイル転送値を代入する document.getElementById('progress').value = progress_value; // 進捗率が100%になったら終了の処理をする if (progress_value == 100) { // 通信が完了したらレスポンスをコンソールに出力する req.addEventListener('readystatechange', () => { // ここでレスポンス結果を制御する console.log("レスポンス結果"); }); result.innerHTML += '通信処理の終了' + '<br />'; result.innerHTML += 'レファイルアップロードのテスト end' + '<br />'; } } }); // ファイルが選択されたときに処理を実行するようイベントリスナーに登録 input_file = document.getElementById("file1"); input_file.addEventListener('change', function(e) { form_data.append('file1', e.target.files[0]); }); // ファイルアップロードの中止ボタン element_stop_file_upload.addEventListener('click', function(e) { req.abort(); }); // ファイル送信 req.send(form_data); } </script> </body> </html>
上記の画面にアクセスし、サイズの大きいファイルを転送中に、
「アップロード中止」のボタンを押すと、転送が中止されます。
ポイントとなる箇所は以下の箇所です。
// ファイルアップロードの中止ボタン element_stop_file_upload.addEventListener('click', function(e) { req.abort(); });
通信用XMLHttpRequestを生成した後、XMLHttpRequestオブジェクトに対してabortメソッドを実行しています。
また、一度停止した通信処理は、またファイル送信処理を実行すると
最初からファイルが転送されます。
レジューム機能を伴ったアップロード方法にするには、転送するファイルに
一意なIDを付与し、そのIDをもとにサーバに転送済のファイル要領を確認し、
未転送バイトからのアップロードをする。といった一連の処理が必要になります。
(今回の投稿ではその方法は試しませんが、別な投稿でまとめるかもしれません)