ホームページ バックエンド開発 PHPチュートリアル フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

Dec 26, 2016 pm 02:01 PM

アップロードの再開については長い間聞いていましたが、フロントエンドでも実装できます。フロントエンドでのブレークポイント再開ダウンロードの実装は主に HTML5 の新機能に依存しているため、一般に古いブラウザーでのサポートは高くありません。

この記事では、一般的な実装プロセスを理解するために、ブレークポイント再開 (フロントエンド ファイル送信 + バックエンド PHP ファイル受信) の簡単な例を使用しています

最終的な外観を確認するために例として写真を見てみましょう

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

1. いくつかの知識の準備

ブレークポイントで転送を再開する ブレークがあるため、ファイルを分割して断片的に転送するプロセスが必要です。

以前はファイルを分割することができませんでしたが、HTML5の新機能の導入により、通常の文字列や配列の分割と同様にsliceメソッドを使ってファイルを分割できるようになりました。

ブレークポイント再開の最も基本的な実装は次のとおりです。フロントエンドは FileList オブジェクトを通じて対応するファイルを取得し、指定された分割方法に従って大きなファイルをセグメントに分割し、それを少しずつバックエンドに渡します。 、バックエンド セグメントを順に使用してファイルを連結します。

そして、送信する前に FileList オブジェクトを変更する必要があります。前の記事では、この種の送信に関するいくつかの注意点を学びました。FileList オブジェクトは直接変更できないため、.submit( を通じて直接アップロードすることはできません。 ) フォームのメソッドを FormData オブジェクトと組み合わせて新しいデータを生成し、Ajax 経由でアップロードする必要があります。

2. 実装プロセス

この例では、ブレークポイントでファイルのアップロードを再開する基本的な機能が実装されていますが、手動の「アップロードの一時停止」操作はまだ正常に実装されていません。アップロードを中断して「中断」を体験してください。

他にも小さなバグがあるかもしれませんが、基本的なロジックはほぼ同じです。

1. フロントエンド実装

まずファイルを選択し、選択したファイルリスト情報をリストし、アップロード操作をカスタマイズできます

(1) まずページのDOM構造を設定します

<!-- 上传的表单 -->
<form method="post" id="myForm" action="/fileTest.php" enctype="multipart/form-data">
<input type="file" id="myFile" multiple>
<!-- 上传的文件列表 -->
<table id="upload-list">
<thead>
<tr>
<th width="35%">文件名</th>
<th width="15%">文件类型</th>
<th width="15%">文件大小</th>
<th width="20%">上传进度</th>
<th width="15%">
<input type="button" id="upload-all-btn" value="全部上传">
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</form>
<!-- 上传文件列表中每个文件的信息模版 -->
<script type="text/template" id="file-upload-tpl"> <tr> <td>{{fileName}}</td> <td>{{fileType}}</td> <td>{{fileSize}}</td> <td class="upload-progress">{{progress}}</td> <td> <input type="button" class="upload-item-btn" data-name="{{fileName}}" data-size="{{totalSize}}" data-state="default" value="{{uploadVal}}"> </td> </tr> </script>
ログイン後にコピー

ここで CSS スタイルを捨てます

<style type="text/css">
body {
font-family: Arial; }
form {
margin: 50px auto;
width: 600px; }
input[type="button"] {
cursor: pointer; }
table {
display: none;
margin-top: 15px;
border: 1px solid #ddd;
border-collapse: collapse; }
table th {
color: #666; }
table td,
table th {
padding: 5px;
border: 1px solid #ddd;
text-align: center;
font-size: 14px; }
</style>
ログイン後にコピー

(2) 次は JS 実装の分析です

FileList オブジェクトを通じてファイルに関する情報を取得できます

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

サイズはファイルのサイズです、ファイルのサイズは分割とシャーディングに依存します

ここでのサイズはバイト数なので、インターフェイスにファイルサイズが表示されると、次のように変換できます

// 计算文件大小 size = file.size > 1024 ? file.size / 1024 > 1024 ? file.size / (1024 * 1024) > 1024 ? (file.size / (1024 * 1024 * 1024)).toFixed(2) + &#39;GB&#39; : (file.size / (1024 * 1024)).toFixed(2) + &#39;MB&#39; : (file.size / 1024).toFixed(2) + &#39;KB&#39; : (file.size).toFixed(2) + &#39;B&#39;;
ログイン後にコピー

ファイルを選択した後、ファイル情報を表示し、テンプレート内のデータを置き換えます

// 更新文件信息列表 uploadItem.push(uploadItemTpl
.replace(/{{fileName}}/g, file.name)
.replace(&#39;{{fileType}}&#39;, file.type || file.name.match(/\.\w+$/) + &#39;文件&#39;)
.replace(&#39;{{fileSize}}&#39;, size)
.replace(&#39;{{progress}}&#39;, progress)
.replace(&#39;{{totalSize}}&#39;, file.size)
.replace(&#39;{{uploadVal}}&#39;, uploadVal)
);
ログイン後にコピー

ただし、ファイル情報を表示する場合、ブレークポイントからアップロードを再開するには、そのファイルが以前にアップロードされている可能性があるため、判断が必要です。インターフェイス上にプロンプ​​トが表示されます。

ローカルをチェックして、対応するデータがあるかどうかを確認します(ここでの方法は、ローカルレコードが100%アップロードされている場合、アップロードを続行するのではなく再アップロードするというものです)

// 初始通过本地记录,判断该文件是否曾经上传过 percent = window.localStorage.getItem(file.name + &#39;_p&#39;); if (percent && percent !== &#39;100.0&#39;) {
progress = &#39;已上传 &#39; + percent + &#39;%&#39;;
uploadVal = &#39;继续上传&#39;;
}
ログイン後にコピー

表示ファイル情報リスト

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

クリックしてアップロードを開始すると、対応するファイルをアップロードできます

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

ファイルをアップロードするときは、ファイルをセグメントに分割する必要があります。

たとえば、ここで構成された各セグメントは 1024B、合計チャンク セグメント (最後のセグメントかどうかを判断するために使用されます)、チャンク セグメント、現在のアップロードされた割合などです。
注目すべきはアップロードの一時停止の操作ですが、実はまだ実装していません…

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

次のステップはセグメンテーションです。プロセス

// 设置分片的开始结尾 var blobFrom = chunk * eachSize, // 分段开始 blobTo = (chunk + 1) * eachSize > totalSize ? totalSize : (chunk + 1) * eachSize, // 分段结尾 percent = (100 * blobTo / totalSize).toFixed(1), // 已上传的百分比 timeout = 5000, // 超时时间 fd = new FormData($(&#39;#myForm&#39;)[0]);
 
fd.append(&#39;theFile&#39;, findTheFile(fileName).slice(blobFrom, blobTo)); // 分好段的文件 fd.append(&#39;fileName&#39;, fileName); // 文件名 fd.append(&#39;totalSize&#39;, totalSize); // 文件总大小 fd.append(&#39;isLastChunk&#39;, isLastChunk); // 是否为末段 fd.append(&#39;isFirstUpload&#39;, times === &#39;first&#39; ? 1 : 0); // 是否是第一段(第一次上传)
// 上传之前查询是否以及上传过分片 chunk = window.localStorage.getItem(fileName + &#39;_chunk&#39;) || 0;
chunk = parseInt(chunk, 10);
ログイン後にコピー

文件应该支持覆盖上传,所以如果文件以及上传完了,现在再上传,应该重置数据以支持覆盖(不然后端就直接追加 blob数据了)

// 如果第一次上传就为末分片,即文件已经上传完成,则重新覆盖上传 if (times === &#39;first&#39; && isLastChunk === 1) { window.localStorage.setItem(fileName + &#39;_chunk&#39;, 0);
chunk = 0;
isLastChunk = 0;
}
ログイン後にコピー

这个 times 其实就是个参数,因为要在上一分段传完之后再传下一分段,所以这里的做法是在回调中继续调用这个上传操作

フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)

接下来就是真正的文件上传操作了,用Ajax上传,因为用到了FormData对象,所以不要忘了在$.ajax({}加上这个配置processData: false

上传了一个分段,通过返回的结果判断是否上传完毕,是否继续上传

success: function(rs) {
rs = JSON.parse(rs); // 上传成功 if (rs.status === 200) { // 记录已经上传的百分比 window.localStorage.setItem(fileName + &#39;_p&#39;, percent); // 已经上传完毕 if (chunk === (chunks - 1)) {
$progress.text(msg[&#39;done&#39;]);
$this.val(&#39;已经上传&#39;).prop(&#39;disabled&#39;, true).css(&#39;cursor&#39;, &#39;not-allowed&#39;); if (!$(&#39;#upload-list&#39;).find(&#39;.upload-item-btn:not(:disabled)&#39;).length) {
$(&#39;#upload-all-btn&#39;).val(&#39;已经上传&#39;).prop(&#39;disabled&#39;, true).css(&#39;cursor&#39;, &#39;not-allowed&#39;);
}
} else { // 记录已经上传的分片 window.localStorage.setItem(fileName + &#39;_chunk&#39;, ++chunk);
$progress.text(msg[&#39;in&#39;] + percent + &#39;%&#39;); // 这样设置可以暂停,但点击后动态的设置就暂停不了.. // if (chunk == 10) { // isPaused = 1; // } console.log(isPaused);
if (!isPaused) {
startUpload();
}
}
}
// 上传失败,上传失败分很多种情况,具体按实际来设置 else if (rs.status === 500) {
$progress.text(msg[&#39;failed&#39;]);
}
},
error: function() {
$progress.text(msg[&#39;failed&#39;]);
}
ログイン後にコピー

2. 后端实现

要注意一下,通过FormData对象上传的文件对象,在PHP中也是通过$_FILES全局对象获取的,还有为了避免上传后文件中文的乱码,用一下iconv
断点续传支持文件的覆盖,所以如果已经存在完整的文件,就将其删除

// 如果第一次上传的时候,该文件已经存在,则删除文件重新上传 if ($isFirstUpload == &#39;1&#39; && file_exists(&#39;upload/&#39;. $fileName) && filesize(&#39;upload/&#39;. $fileName) == $totalSize) {
unlink(&#39;upload/&#39;. $fileName);
}
ログイン後にコピー

使用上述的两个方法,进行文件信息的追加,别忘了加上 FILE_APPEND 这个参数~

// 继续追加文件数据 if (!file_put_contents(&#39;upload/&#39;. $fileName, file_get_contents($_FILES[&#39;theFile&#39;][&#39;tmp_name&#39;]), FILE_APPEND)) {
$status = 501;
} else { // 在上传的最后片段时,检测文件是否完整(大小是否一致) if ($isLastChunk === &#39;1&#39;) { if (filesize(&#39;upload/&#39;. $fileName) == $totalSize) {
$status = 200;
} else {
$status = 502;
}
} else {
$status = 200;
}
}
ログイン後にコピー

一般在传完后都需要进行文件的校验吧,所以这里简单校验了文件大小是否一致。

根据实际需求的不同有不同的错误处理方法,这里就先不多处理了

完整的PHP部分

 0) {
$status = 500;
} else { // 此处为一般的文件上传操作 // if (!move_uploaded_file($_FILES['theFile']['tmp_name'], 'upload/'. $_FILES['theFile']['name'])) { // $status = 501; // } else { // $status = 200; // } // 以下部分为文件断点续传操作 // 如果第一次上传的时候,该文件已经存在,则删除文件重新上传 if ($isFirstUpload == &#39;1&#39; && file_exists(&#39;upload/&#39;. $fileName) && filesize(&#39;upload/&#39;. $fileName) == $totalSize) {
unlink(&#39;upload/&#39;. $fileName);
} // 否则继续追加文件数据 if (!file_put_contents('upload/'. $fileName, file_get_contents($_FILES['theFile']['tmp_name']), FILE_APPEND)) {
$status = 501;
} else { // 在上传的最后片段时,检测文件是否完整(大小是否一致) if ($isLastChunk === '1') { if (filesize('upload/'. $fileName) == $totalSize) { $status = 200;
} else {
$status = 502;
}
} else {
$status = 200;
}
}
} echo json_encode(array( 'status' => $status, 'totalSize' => filesize('upload/'. $fileName), 'isLastChunk' => $isLastChunk
)); ?>
ログイン後にコピー

   

更多フロントエンドはブレークポイントを実装してファイルのアップロードを再開します (フロントエンドのファイル送信 + バックエンドの PHP ファイル受信)相关文章请关注PHP中文网!

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Laravelでフラッシュセッションデータを使用します Laravelでフラッシュセッションデータを使用します Mar 12, 2025 pm 05:08 PM

Laravelは、直感的なフラッシュメソッドを使用して、一時的なセッションデータの処理を簡素化します。これは、アプリケーション内に簡単なメッセージ、アラート、または通知を表示するのに最適です。 データは、デフォルトで次の要求のためにのみ持続します。 $リクエスト -

PHPのカール:REST APIでPHPカール拡張機能を使用する方法 PHPのカール:REST APIでPHPカール拡張機能を使用する方法 Mar 14, 2025 am 11:42 AM

PHPクライアントURL(CURL)拡張機能は、開発者にとって強力なツールであり、リモートサーバーやREST APIとのシームレスな対話を可能にします。尊敬されるマルチプロトコルファイル転送ライブラリであるLibcurlを活用することにより、PHP Curlは効率的なexecuを促進します

Laravelテストでの簡略化されたHTTP応答のモッキング Laravelテストでの簡略化されたHTTP応答のモッキング Mar 12, 2025 pm 05:09 PM

Laravelは簡潔なHTTP応答シミュレーション構文を提供し、HTTP相互作用テストを簡素化します。このアプローチは、テストシミュレーションをより直感的にしながら、コード冗長性を大幅に削減します。 基本的な実装は、さまざまな応答タイプのショートカットを提供します。 Illuminate \ support \ facades \ httpを使用します。 http :: fake([[ 'google.com' => 'hello world'、 'github.com' => ['foo' => 'bar']、 'forge.laravel.com' =>

Laravelサービスプロバイダーを登録および使用する方法 Laravelサービスプロバイダーを登録および使用する方法 Mar 07, 2025 am 01:18 AM

Laravelのサービスコンテナとサービスプロバイダーは、そのアーキテクチャの基本です。 この記事では、サービスコンテナ、詳細サービスプロバイダーの作成、登録、および実用的な使用法を例で説明します。 Oveから始めます

Codecanyonで12の最高のPHPチャットスクリプト Codecanyonで12の最高のPHPチャットスクリプト Mar 13, 2025 pm 12:08 PM

顧客の最も差し迫った問題にリアルタイムでインスタントソリューションを提供したいですか? ライブチャットを使用すると、顧客とのリアルタイムな会話を行い、すぐに問題を解決できます。それはあなたがあなたのカスタムにより速いサービスを提供することを可能にします

PHPロギング:PHPログ分析のベストプラクティス PHPロギング:PHPログ分析のベストプラクティス Mar 10, 2025 pm 02:32 PM

PHPロギングは、Webアプリケーションの監視とデバッグ、および重要なイベント、エラー、ランタイムの動作をキャプチャするために不可欠です。システムのパフォーマンスに関する貴重な洞察を提供し、問題の特定に役立ち、より速いトラブルシューティングをサポートします

PHPにおける後期静的結合の概念を説明します。 PHPにおける後期静的結合の概念を説明します。 Mar 21, 2025 pm 01:33 PM

記事では、PHP 5.3で導入されたPHPの後期静的結合(LSB)について説明し、より柔軟な継承を求める静的メソッドコールのランタイム解像度を可能にします。 LSBの実用的なアプリケーションと潜在的なパフォーマ

フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 Mar 28, 2025 pm 05:12 PM

この記事では、フレームワークにカスタム機能を追加し、アーキテクチャの理解、拡張ポイントの識別、統合とデバッグのベストプラクティスに焦点を当てています。

See all articles