ファイルアップロードのための2つのソリューションファイルストリーム(フォームデータ)に基づくelement-ui フレームワークのアップロード コンポーネントは、デフォルトでファイル ストリームに基づいています。
クライアントはファイルをbase64に変換するfileRead.readAsDataURL(file) を介して base64 文字列に変換した後、送信前に encodeURIComponent でコンパイルする必要があります。送信されたデータは qs.stringify によって処理され、リクエスト ヘッダーに "Content-Type": "application/x-www-form-urlencoded" が追加されます。 大きなファイルのアップロードまず、element-ui を使用してページを構築します。アップロードの実装をカスタマイズするため、el-upload コンポーネントの auto-upload を false に設定する必要があります。action は必須のパラメータであり、ここで値を入力する必要はありません。 <テンプレート> <div id="アプリ"> <!-- コンポーネントをアップロード --> <el-upload アクション ドラッグ :auto-upload="false" :show-file-list="false" :on-change="handleChange"> <i class="el-icon-upload"></i> <div class="el-upload__text">ファイルをここにドラッグするか、<em>クリックしてアップロード</em></div> <div class="el-upload__tip" slot="tip">ビデオのサイズは 200M を超えません</div> </el-アップロード> <!-- 進行状況の表示--> <div class="progress-box"> <span>アップロードの進行状況: {{ percent.toFixed() }}%</span> <el-button type="primary" size="mini" @click="handleClickBtn">{{ アップロード | btnTextFilter}}</el-button> </div> <!-- 正常にアップロードされたビデオを表示します--> <div v-if="ビデオURL"> <video :src="videoUrl" コントロール /> </div> </div> </テンプレート> ファイルオブジェクトを取得し、ArrayBufferオブジェクトに変換します。後でハッシュ値とファイル名を生成するために SparkMD5 ライブラリを使用するため、ArrayBuffer に変換します。 非同期handleChange(ファイル) { 定数 fileObj = file.raw 試す{ const バッファ = this.fileToBuffer(fileObj) を待機します console.log(バッファ) }キャッチ(e){ コンソール.log(e) } } プリントバッファの結果は次のようになります 注意: before-upload 関数と on-change 関数の両方にパラメータとして file がありますが、on-change の file は File オブジェクトではありません。File オブジェクトを取得するには、file.raw を使用する必要があります。 ここでは、FileReader クラスを使用して、File オブジェクトを ArrayBuffer オブジェクトに変換します。これは非同期プロセスであるため、Promise でカプセル化されています。 // File オブジェクトを ArrayBuffer に変換します fileToBuffer(ファイル) { 新しい Promise を返します ((resolve, reject) => { const fr = 新しい FileReader() fr.onload = e => { 解決(e.target.result) } fr.readAsArrayBuffer(ファイル) fr.onerror = () => { 拒否(新しいエラー('ファイル形式の変換エラー')) } }) } スライスを作成するファイルは、固定サイズまたは固定数で複数の部分に分割できます。js で使用される IEEE754 バイナリ浮動小数点演算標準によって発生するエラーを回避するために、ファイルを固定サイズでカットし、各スライスのサイズを 2M に設定することにしました。つまり、2M = 21024KB = 21024*1024B = 2097152B です。 Blob.slice()はファイルを切り取るために使用されます // ファイルを固定サイズ (2M) にスライスします。ここでは複数の定数が宣言されていることに注意してください。const chunkSize = 2097152, chunkList = [], // すべてのスライスを保持する配列 chunkListLength = Math.ceil(fileObj.size / chunkSize), // スライスの合計数を計算 suffix = /\.([0-9A-z]+)$/.exec(fileObj.name)[1] // ファイルサフィックス // ファイルの内容に基づいてハッシュ値を生成する const spark = new SparkMD5.ArrayBuffer() spark.append(バッファ) 定数ハッシュ = spark.end() // スライスを生成します。バックエンドでは、渡されるパラメータとしてバイトデータチャンク (chunk) と各データチャンクのファイル名 (fileName) が必要です。 let curChunk = 0 // スライス時の初期位置 for (let i = 0; i < chunkListLength; i++) { 定数項目 = { チャンク: fileObj.slice(curChunk, curChunk + chunkSize), fileName: `${hash}_${i}.${suffix}` // ファイル名はhash_1.jpgに従って命名されます} curChunk += チャンクサイズ chunkList.push(アイテム) } console.log(チャンクリスト) ファイルを選択すると、次のような印刷結果が表示されます。 リクエストを送信リクエストの送信は並列またはシリアルで行うことができます。ここではシリアル送信を選択します。各スライスごとに新しいリクエストが作成されます。ブレークポイントの再開を実現するために、リクエストを関数 fn にカプセル化し、配列 requestList を使用してリクエスト セットを保存し、リクエスト送信用の send 関数をカプセル化します。このようにして、一時停止ボタンが押されると、アップロードを簡単に終了できます。コードは次のとおりです。 リクエストを送信します(){ const requestList = [] // リクエストコレクション this.chunkList.forEach(item => { 定数fn = () => { const フォームデータ = 新しいフォームデータ() formData.append('チャンク', item.チャンク) formData.append('ファイル名', item.fileName) 戻り値: axios({ URL: '/single3', メソッド: 'post'、 ヘッダー: { 'Content-Type': 'multipart/form-data' }, データ: フォームデータ }).then(res => { if (res.data.code === 0) { // 成功if (this.percentCount === 0) { this.パーセントカウント = 100 / this.チャンクリストの長さ } this.percent += this.percentCount // 進行状況を変更} }) } リクエストリストをプッシュ(fn) }) let i = 0 // 送信されたリクエストの数を記録する const send = async () => { // if ('pause') 戻り値 if (i >= リクエストリストの長さ) { //完了したリターンを送信する } リクエストリスト[i]()を待つ 私は++ 送信() } send() // リクエストを送信する}, axios 部分は、次の形式で直接記述することもできます。 axios.post('/single3', フォームデータ, { ヘッダー: { 'Content-Type': 'multipart/form-data' } }) すべてのスライスが正常に送信された後バックエンドインターフェースに従って、別の get リクエストが送信され、ファイルのハッシュ値がサーバーに渡されます。これを実装するための完全なメソッドを定義します。ここでは、送信されるファイルはビデオファイルであると想定しています。 const 完全 = () => { アクシオス({ URL: '/merge', メソッド: 'get'、 パラメータ: { ハッシュ: this.hash } }).then(res => { if (res.data.code === 0) { // リクエストが正常に送信されました this.videoUrl = res.data.path } }) } この方法では、ファイルが正常に送信された後、ページで送信されたビデオを閲覧できます。 履歴書のダウンロードまず、一時停止ボタンのテキストが処理されます。フィルターが使用されます。アップロード値が true の場合は「一時停止」が表示され、それ以外の場合は「続行」が表示されます。 フィルター: btnTextFilter(val) { 戻り値 ? '一時停止' : '続行' } } 一時停止ボタンが押されると、handleClickBtnメソッドがトリガーされます。 ハンドルクリックボタン() { this.upload = !this.upload // 一時停止されていない場合はアップロードを続行します if (this.upload) this.sendRequest() } スライスを送信するには、send メソッドの先頭に if (!this.upload) return を追加します。これにより、アップロード変数が false である限り、アップロードは続行されません。一時停止後に送信を継続するには、スライスの送信が成功するたびにchunkList配列からスライスを削除する必要があります。this.chunkList.splice(index, 1) コードの概要<テンプレート> <div id="アプリ"> <!-- コンポーネントをアップロード --> <el-upload アクション ドラッグ :auto-upload="false" :show-file-list="false" :on-change="handleChange"> <i class="el-icon-upload"></i> <div class="el-upload__text">ファイルをここにドラッグするか、<em>クリックしてアップロード</em></div> <div class="el-upload__tip" slot="tip">ビデオのサイズは 200M を超えません</div> </el-アップロード> <!-- 進行状況の表示--> <div class="progress-box"> <span>アップロードの進行状況: {{ percent.toFixed() }}%</span> <el-button type="primary" size="mini" @click="handleClickBtn">{{ アップロード | btnTextFilter}}</el-button> </div> <!-- 正常にアップロードされたビデオを表示します--> <div v-if="ビデオURL"> <video :src="videoUrl" コントロール /> </div> </div> </テンプレート> <スクリプト> 「spark-md5」からSparkMD5をインポートします。 「axios」からaxiosをインポートします エクスポートデフォルト{ 名前: 'App3'、 フィルター: btnTextFilter(val) { 戻り値 ? '一時停止' : '続行' } }, データ() { 戻る { パーセント: 0, ビデオURL: ''、 アップロード: true、 パーセントカウント: 0 } }, メソッド: { 非同期handleChange(ファイル) { if (!file) 戻り値 パーセント = 0 this.videoUrl = '' // ファイルを取得してArrayBufferオブジェクトに変換します。const fileObj = file.raw バッファリング 試す { バッファ = this.fileToBuffer(fileObj) を待機します } キャッチ (e) { コンソール.log(e) } // ファイルを固定サイズ (2M) にスライスします。ここでは複数の定数が宣言されていることに注意してください。const chunkSize = 2097152, chunkList = [], // すべてのスライスを保持する配列 chunkListLength = Math.ceil(fileObj.size / chunkSize), // スライスの合計数を計算 suffix = /\.([0-9A-z]+)$/.exec(fileObj.name)[1] // ファイルサフィックス // ファイルの内容に基づいてハッシュ値を生成する const spark = new SparkMD5.ArrayBuffer() spark.append(バッファ) 定数ハッシュ = spark.end() // スライスを生成します。バックエンドでは、渡されるパラメータとしてバイトデータチャンク (chunk) と各データチャンクのファイル名 (fileName) が必要です。 let curChunk = 0 // スライス時の初期位置 for (let i = 0; i < chunkListLength; i++) { 定数項目 = { チャンク: fileObj.slice(curChunk, curChunk + chunkSize), fileName: `${hash}_${i}.${suffix}` // ファイル名はhash_1.jpgに従って命名されます} curChunk += チャンクサイズ chunkList.push(アイテム) } this.chunkList = chunkList // sendRequest は this.hash = hash を使用する必要があります // sendRequest は this.sendRequest() を使用する必要があります }, // リクエストを送信する sendRequest() { const requestList = [] // リクエストコレクション this.chunkList.forEach((item, index) => { 定数fn = () => { const フォームデータ = 新しいフォームデータ() formData.append('チャンク', item.チャンク) formData.append('ファイル名', item.fileName) 戻り値: axios({ URL: '/single3', メソッド: 'post'、 ヘッダー: { 'Content-Type': 'multipart/form-data' }, データ: フォームデータ }).then(res => { if (res.data.code === 0) { // Successif (this.percentCount === 0) { // アップロードが成功した後にスライスを削除し、chunkList の長さを変更して percentCount の値に影響を与えないようにしますthis.percentCount = 100 / this.chunkList.length } this.percent += this.percentCount // 進行状況を変更します this.chunkList.splice(index, 1) // アップロードが成功したら、ブレークポイントの再開を容易にするためにこのチャンクを削除します} }) } リクエストリストをプッシュ(fn) }) let i = 0 // 送信されたリクエストの数を記録する // すべてのファイルスライスが送信されたら、'/merge' インターフェースを要求し、ファイルハッシュをサーバーに渡す必要があります const complete = () => { アクシオス({ URL: '/merge', メソッド: 'get'、 パラメータ: { ハッシュ: this.hash } }).then(res => { if (res.data.code === 0) { // リクエストが正常に送信されました this.videoUrl = res.data.path } }) } const send = 非同期() => { if (!this.upload) 戻り値 if (i >= リクエストリストの長さ) { // 送信完了() 戻る } リクエストリスト[i]()を待つ 私は++ 送信() } send() // リクエストを送信する}, // 一時停止ボタンを押す handleClickBtn() { this.upload = !this.upload // 一時停止されていない場合はアップロードを続行します if (this.upload) this.sendRequest() }, // File オブジェクトを ArrayBuffer に変換します fileToBuffer(ファイル) { 新しい Promise を返します ((resolve, reject) => { const fr = 新しい FileReader() fr.onload = e => { 解決(e.target.result) } fr.readAsArrayBuffer(ファイル) fr.onerror = () => { 拒否(新しいエラー('ファイル形式の変換エラー')) } }) } } } </スクリプト> <スタイルスコープ> .progress-box { ボックスのサイズ: 境界線ボックス; 幅: 360ピクセル; ディスプレイ: フレックス; コンテンツの両端揃え: スペースの間; アイテムの位置を中央揃えにします。 上マージン: 10px; パディング: 8px 10px; 背景色: #ecf5ff; フォントサイズ: 14px; 境界線の半径: 4px; } </スタイル> 効果は以下のとおりです。 もう一つフォームデータここでデータを送信するには FormData を使用します。エンコード タイプが "multipart/form-data" に設定されている場合、フォームと同じ形式が使用されます。 フォームデータの追加()FormData オブジェクト内の既存のキーに新しい値が追加されるか、キーが存在しない場合はキーが追加されます。このメソッドは、formData.append(name, value, filename) の 3 つのパラメータを渡すことができます。ここで、filename はオプションのパラメータであり、サーバーに渡されるファイル名です。2 番目のパラメータとして Blob または File が使用される場合、Blob オブジェクトのデフォルトのファイル名は "blob" になります。 File オブジェクトのデフォルトのファイル名は、ファイルの名前です。 Vue の大容量ファイルアップロードとブレークポイント再開の実装に関するこの記事はこれで終わりです。Vue の大容量ファイルアップロードとブレークポイント再開の関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: mysql-8.0.15-winx64 解凍バージョンのインストールチュートリアルと終了する 3 つの方法
>>: 仮想マシンを作成し、VMware に Redhat Linux オペレーティング システムをインストールする (グラフィック チュートリアル)
仮想マシンソフトウェア: VMware Workstationイメージ: deepin-deskto...
目次MySQL マルチバージョン同時実行1. マルチバージョン同時実行制御1. 一貫した読み取り2....
インストール環境: CentOS7 64ビットMINI版、MySQL5.7をインストール1. YUM...
この記事では、CentOSでのMySQLの完全アンインストールについて記録しています。具体的な内容は...
目次1. 事前分析1. 変数の事前解析と関数の事前解析1. 変数の事前解析2. 機能事前分析2. 事...
まず、一連の概念を理解しましょう。nginx リバース プロキシとは何でしょうか?リバース プロキシ...
<br />関連記事: Web コンテンツ ページ作成に関する 9 つの実用的な提案、W...
ご存知のとおり、コンピューターには 2 種類の画像があり、1 つはビットマップ、もう 1 つはベクタ...
フレームとは、Web ページ画面を複数のフレームに分割したもの(複数の Web ページという形で表示...
序文著者は、アプリケーションからフレームワーク、オペレーティング システムに至るまで、あらゆるコード...
<br />矛盾が生じます。私たちのような小さな工房では、デザインとレイアウトは基本的に...
この記事の例では、古典的なマインスイーパゲームを実装するためのjsの具体的なコードを参考までに共有し...
目次1. はじめに2. シナリオ3. 環境を整える3.1 環境変数の挿入4. 最後に1. はじめに一...
序文ゲートウェイプロジェクトを開発する場合、署名 sign_key 情報はリクエスト時にリクエスト ...
最近、インターネットのベテランと「広告」について議論したのですが、彼から非常に興味深い意見を聞きまし...