1. はじめに以前、同社は管理システムにグローバルアップロードプラグインを作成したいと考えていました。つまり、ページを切り替えてもアップロードインターフェースはそのまま残り、アップロードには影響しません。これは、Vue などの SPA フレームワークの前では問題になりません。しかし、バックエンドのボスは、マルチパートアップロード、インスタントアップロード、ブレークポイント再開アップロードの機能を実装する必要があると言っており、これは非常に困難に思えます。 以前、webuploader に関する記事を書きましたが、使用中に多くの問題が見つかり、公式チームはこのプラグインをメンテナンスしなくなりました。何日もの研究と失敗を経て、最終的に、プロジェクトでの使用に苦労せず安定している 基本的な(カスタマイズされていない)アップロード機能だけを実装したい場合は、 この記事のソースコードはここにあります: https://github.com/shady-xia/Blog/tree/master/vue-simple-uploader 2. vue-simple-uploaderについて
この記事を読む前に、まず simple-uploader.js ドキュメント インストール: 'vue-simple-uploader' からアップローダーをインポートします。 Vue.use(アップローダー) 3. vue-simple-uploaderをベースにグローバルアップロードコンポーネントをカプセル化する
テンプレート部分は以下のとおりです。テンプレートとスタイルをカスタマイズしたので、HTML 部分が比較的長くなっています。CSS 部分は今のところ記載していません。独自の UI に合わせて変更できます。主に、 <テンプレート> <div id="グローバルアップローダー"> <!-- アップロード --> <アップローダー ref="アップローダー" :options="オプション" :autoStart="false" @ファイルが追加されました="onFileAdded" @file-success="onFileSuccess" @file-progress="onFileProgress" @file-error="onFileError" クラス="アップローダーアプリ"> <アップローダー非サポート></アップローダー非サポート> <uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn">ファイルを選択</uploader-btn> <uploader-list v-show="panelShow"> <div class="file-panel" slot-scope="props" :class="{'collapse': collapse}"> <div class="ファイルタイトル"> <h2>ファイルリスト</h2> <div class="操作"> <el-button @click="fileListShow" type="text" :title="折りたたむ ? '展開':'折りたたむ' "> <i class="iconfont" :class="collapse ? 'icon-fullscreen': 'icon-minus-round'"></i> </el-button> <el-button @click="close" type="text" title="閉じる"> <i class="iconfont icon-close"></i> </el-button> </div> </div> <ul class="ファイルリスト"> <li v-for="props.fileList 内のファイル" :key="file.id"> <uploader-file :class="'file_' + file.id" ref="files" :file="file" :list="true"></uploader-file> </li> <div class="no-file" v-if="!props.fileList.length"><i class="nucfont inuc-empty-file"></i> アップロードするファイルがありません</div> </ul> </div> </アップローダーリスト> </アップローダー> </div> </テンプレート> コンポーネント内のデータ部分: データ() { 戻る { オプション: target: 'http://xxxxx/xx', // アップロード先のURL chunkSize: '2048000', // チャンクサイズ fileParameterName: 'file', // ファイルをアップロードするときのファイルパラメータ名、デフォルトファイル maxChunkRetries: 3, // 自動で失敗したアップロードの最大再試行回数 testChunks: true, // サーバーの断片化検証を有効にするかどうか // サーバーの断片化検証機能、インスタントアップロードとブレークポイント再開の基礎 checkChunkUploadedByResponse: function (chunk, message) { objMessage = JSON.parse(message); アップロードをスキップする場合 true を返します。 } 戻り値 (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0 }, ヘッダー: { // ヘッダーに検証が追加されました。実際の業務に応じて設定してください。Authorization: "Bearer " + Ticket.get().access_token }, }, 属性: { // 受け入れられるファイルタイプ (['.png'、'.jpg'、'.jpeg'、'.gif'、'.bmp'...] など) ここで accept をカプセル化します: ACCEPT_CONFIG.getAll() }, panelShow: false, //ファイルを選択した後、アップロードパネルを表示します } }, グローバル参照: <グローバルアップローダー></グローバルアップローダー> 4. ファイルアップロードプロセスの概要1. ボタンをクリックしてファイルのアップロード操作を開始します。 (グローバルアップロード機能を使用せず、直接アップロードをクリックする場合は、この手順を無視してください。) グローバルアップロードプラグインを作成しているため、まずアップロードウィンドウを非表示にする必要があります。アップロードボタンをクリックすると、Bus を使用して 特定のページで、アップロードボタンをクリックし、パラメータ(ある場合)をバックグラウンドに移動します。ここでは、 バス.$emit('openUploader', { 上位ID: this.上位ID }) Bus.$on('openUploader', クエリ => { this.params = クエリ || {}; (this.$refs.uploadBtn)の場合{ // ファイル選択ウィンドウが開きます$('#global-uploader-btn').click(); } }); 2. ファイルを選択すると、アップロードウィンドウが表示され、md5計算が開始されます。 onFileAdded(ファイル) { this.panelShow = true; // 以下で説明する MD5 を計算します this.computeMD5(file); }, ここには前提があります。 ファイルを選択した後、ブレークポイント再開と即時送信の機能を実装するために MD5 を計算する必要があります。したがって、ファイルを選択した後すぐにアップロードを開始することはできません。ファイルのアップロード操作を開始する前に、MD5 の計算が完了するまで待つ必要があります。 具体的なMD5の計算方法については後述しますが、ここでは簡単に紹介します。 アップロードプロセス中、ファイル進行状況のアップロード進行状況コールバックが継続的にトリガーされます。 // ファイル進行状況コールバック onFileProgress(rootFile, file, chunk) { console.log(`${file.name} をアップロードしています、チャンク: ${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`) }, 3. ファイルが正常にアップロードされた後ファイルが正常にアップロードされた後、「アップロード完了」コールバックで、サーバーから返された 注: ここでの onFileSuccess(ルートファイル、ファイル、レスポンス、チャンク) { res = JSON.parse(response); とします。 // サーバー定義のエラー。アップローダーではインターセプトできません。if (!res.result) { this.$message({ メッセージ: res.message、 タイプ: 'error' }); 戻る } // サーバーがマージのリクエストを返す場合 if (res.needMerge) { api.mergeSimpleUpload({ 一時名: res.一時名、 ファイル名: ファイル名、 ...this.params、 })。次に、データ => { // ファイルのマージが成功しました Bus.$emit('fileSuccess', data); }).catch(e => {}); // マージする必要はありません } else { Bus.$emit('fileSuccess', res); console.log('アップロードに成功しました'); } }, onFileError(ルートファイル、ファイル、レスポンス、チャンク) { コンソール.log(エラー) }, 5. ファイルシャーディング
図に示すように、大きなファイルの場合、複数のリクエストが送信されます。testChunks サーバーに送信されたパラメータを確認します。chunkNumber ファイルのアップロードが成功した場合、バックエンドから返されたフィールドは、バックエンドに別のファイルマージ要求を送信するかどうかを判断するために使用されることに注意してください。 6. MD5の計算プロセスブレークポイント再開とインスタント転送の基礎は、ファイルの一意の識別子であるファイルの
/** * ブレークポイントの再開と即時転送を実現するために md5 を計算します* @param ファイル */ /** * ブレークポイントの再開と即時転送を実現するために md5 を計算します* @param ファイル */ computeMD5(ファイル) { fileReader を新しい FileReader() にします。 time = new Date().getTime(); とします。 blobSlice を File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice とします。 現在のチャンクを 0 にします。 定数チャンクサイズ = 10 * 1024 * 1000; chunks = Math.ceil(file.size / chunkSize); とします。 spark を新しい SparkMD5.ArrayBuffer() にします。 //ファイルステータスを「MD5 を計算」に設定する this.statusSet(ファイルID、'md5'); ファイル.一時停止(); ロードNext(); ファイルリーダー.onload = (e => { spark.append(e.target.result); (現在のチャンク < チャンク) の場合 { 現在のチャンク++; ロードNext(); // MD5 計算の進行状況をリアルタイムで表示 this.$nextTick(() => { $(`.myStatus_${file.id}`).text('MD5 を検証 '+ ((currentChunk/chunks)*100).toFixed(0)+'%') }) } それ以外 { md5 = spark.end(); とします。 this.computeMD5Success(md5、ファイル); console.log(`MD5 計算が完了しました: ${file.name} \nMD5: ${md5} \nセグメント: ${chunks} サイズ: ${file.size} 時間: ${new Date().getTime() - time} ms`); } }); fileReader.onerror = 関数(){ this.error(`ファイル ${file.name} の読み取りエラーです。ファイルを確認してください`) ファイル.キャンセル(); }; 関数loadNext() { start = currentChunk * chunkSize とします。 end = ((start + chunkSize) >= file.size) とします。file.size : start + chunkSize; fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end)); } }, computeMD5Success(md5, ファイル) { // カスタムパラメータをアップローダーインスタンスのoptsに直接ロードします。Object.assign(this.uploader.opts, { クエリ: { ...this.params、 } }) ファイル.uniqueIdentifier = md5; ファイル.resume(); this.statusRemove(ファイル.id); }, ファイルの uniqueIdentifier プロパティに値を割り当てた後、リクエスト内の識別子は計算された MD5 になります。 7. 即時アップロードと再開ダウンロード
サーバーは、フロントエンドから送信された
7.1 フロントエンドの場合各アップロード プロセスの開始時に、 このリクエストにはいくつかの結果が考えられます: a. 2 回目のアップロードの場合は、リクエスト結果に対応するマークが表示されます。たとえば、ここでは 図a1: 即時送信の場合のバックエンド戻り値 図a2: GIF送信 b. バックエンドがフラグメント情報を返す場合、これはブレークポイントの再開です。図に示すように、返されたデータには 図b1: ブレークポイント再開時のバックエンド戻り値 図 b2: ブレークポイント再開 gif c. 何も返されない場合、これはまったく新しいファイルであり、完全なマルチパートアップロードロジックが実行されます。 7.2 フロントエンドの断片化チェック: checkChunkUploadedByResponse前回は概念について説明しました。次は、フロントエンドがこれらの戻り値をどのように処理するかについて説明します。 checkChunkUploadedByResponse: 関数 (チャンク、メッセージ) { objMessage = JSON.parse(message); アップロードをスキップする場合 true を返します。 } 戻り値 (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0 }, 注: 8. ソースコードと追記合計でいくつかのファイルがあり、 私のレベルは限られているので、参考までにアイデアを提供しているだけです。 このプラグインをパッケージ化してファイル リソース ライブラリを開発した後、基本的に単純な Baidu Netdisk を実現したことがわかりました。これは、非常に複雑な機能を備えた管理システムであり、詐欺です。 8.1 最初のシャード損失問題についてtestChunk を有効にした後にサーバーが最初のフラグメントを受信できない問題について: testChunk の get リクエストは、デフォルトで最初のフラグメントをサーバーに送信します。サーバーが 200 ステータスを返す場合、現在のチャンクはアップロードされており、再度アップロードされないものとみなされます。 2019/8/6更新 1. ファイルMD5の計算方法を最適化し、MD5の計算の進行状況を表示しました。 前回の記事の 2. カスタムステータスの追加 (私はこれまでにもいくつかのカスタム状態をカプセル化してきました。最近、何人かの友人から「MD5 の検証」と「マージ」状態がないのはなぜかと尋ねられました。私は独自の方法を書きました。この方法は愚かですが、効果は得られます) プラグインはもともと、 ビジネス上のニーズにより、 最初のいくつかの状態はすでにプラグインにパッケージ化されているため、ソース コードを変更することはできず、よりハッキーなアプローチしか使用できません。 this.statusSet(file.id, 'マージ中'); this.statusRemove(ファイル.id); 具体的な使い方についてはソースコードを参照してください。同時に、simple-uploader のプラグイン作者が将来的にカスタムステータスの設定をサポートすることを期待しています。 これで、ファイルセグメントアップロード、インスタントアップロード、ブレークポイント再開のための vue-simple-uploader カプセル化に基づくグローバルアップロードプラグイン機能に関するこの記事は終了です。vue simple uploader カプセル化に関するその他の関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: MySQL が起動直後にシャットダウンする問題 (ibdata1 ファイルの破損が原因) に対する完璧な解決策
>>: docker-compose でデプロイしたときに MySQL にアクセスできなくなる問題の簡単な分析
目次BOM (ブラウザ オブジェクト モデル) 1. ウィンドウブラウザのウィンドウサイズを取得する...
sudo 設定ファイルsudo のデフォルトの設定ファイルは /etc/sudoers です。一般的...
関連記事:初心者が学ぶ HTML タグ (4)導入された HTML タグは、必ずしも XHTML 仕...
目次JS 関数呼び出し、適用、バインドメソッド1. call() メソッド1. call() メソッ...
共同インデックスこの記事におけるジョイントインデックスの定義は次のとおりです (MySQL): AL...
必要ページング バーを追加します。これにより、ページにジャンプしたり、ページ番号に従って特定のページ...
目次1. リストの走査2. Vueにおけるキーの役割3. リストフィルタリングこの記事では、Vue ...
私は今日、mybatis を学び、データベースに対していくつかの簡単な追加、削除、変更、クエリを実行...
ウェブサイトを見るというのは、実は美しい女性を評価するようなものです。見た目を見るとき、私たちは見た...
1. MySQLをダウンロードする公式サイトのダウンロードアドレス https://dev.mys...
Linux で Ctrl+c、Ctrl+d、Ctrl+z はどういう意味ですか? Ctrl+c と ...
1-ドロップダウン選択ボックスのスタイル設定 - ドロップダウン リストを変更します。 2- <...
UNION演算子の使用union : 2 つ以上の SELECT ステートメントの結果を 1 つの...
この記事では、スライディングカルーセル効果を実現するためのjsの具体的なコードを参考までに共有します...
目次導入取引の4つの特徴トランザクション分離レベル確認するMVCC現在の読書スナップショット読み取り...