今回はReact-Flaskフレームワーク上でアップロードコンポーネントを開発するスキルについてお話します。現在、私は主に React を使用してフロントエンドを開発しています。その過程で、React-Bootstrap、Ant Design、Material UI、Bulma など、多くの興味深いフロントエンド UI フレームワークを知るようになりました。人気のアップロード コンポーネントは多数ありますが、最も多くのユーザーがいるのは jQuery-File-Upload と Dropzone です。一方、急成長している新規参入者には Uppy と filepond があります。 今回はReact-Flaskフレームワーク上でアップロードコンポーネントを開発するスキルについてお話します。現在、私は主に React を使用してフロントエンドを開発しています。その過程で、React-Bootstrap、Ant Design、Material UI、Bulma など、多くの興味深いフロントエンド UI フレームワークを知るようになりました。人気のアップロード コンポーネントは多数ありますが、最も多くのユーザーがいるのは jQuery-File-Upload と Dropzone です。一方、急成長している新規参入者には Uppy と filepond があります。 Fine-Uploader の作者が 2018 年以降メンテナンスを行わないことを決定したのは残念です。後発者として理由を問うつもりはありませんが、オープンソースの作者の皆さんの取り組みを尊重してください。 ここで React-Dropzone を選択する理由は以下のとおりです。
デモ例1. Axios は通常のファイルをアップロードします: yarn を通じて react-dropzone を導入します。 糸 反応ドロップゾーン axios を追加 フロントエンドの js は次のとおりです (不足しているものがある場合は、ご自身で修正してください)。 Reactをインポートします。 使用状態、 コールバックの使用、 使用効果、 } を 'react' から取得します。 'react-dropzone' から {useDropzone} をインポートします。 「./dropzone.styles.css」をインポートします 'react-infinite-scroller' から InfiniteScroll をインポートします。 輸入 { リスト、 メッセージ、 // アバター、 スピン、 } 'antd' から; 'axios' から axios をインポートします。 /** * ファイルサイズを計算 * @param {*} バイト * @param {*} 小数点 * @戻り値 */ 関数formatBytes(バイト、小数点数 = 2) { if (bytes === 0) は '0 バイト' を返します。 定数k = 1024; const dm = 小数点 < 0 ? 0 : 小数点; const sizes = ['バイト', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; 定数 i = Math.floor(Math.log(bytes) / Math.log(k)); parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i] を返します。 } /** * ドロップゾーンアップロードファイル * @param {*} props * @戻り値 */ 関数 DropzoneUpload(props) { const [ファイル、setFiles] = useState([]) const [ロード中、setLoading] = useState(false); const [hasMore, setHasMore] = useState(true); const onDrop = useCallback(acceptedFiles => { 読み込みをtrueに設定します。 フォームデータを作成します。 smallFiles.forEach(ファイル => { formData.append("files", ファイル); }); アクシオス({ メソッド: 'POST'、 url: '/api/files/multiplefiles', データ: フォームデータ、 ヘッダー: { 「コンテンツタイプ」: 「マルチパート/フォームデータ」、 } }) then(応答 => { ファイルを追加します(受け入れられたファイル)。 読み込みを設定します(false); }); }, [ファイル]); // ドロップゾーン設定 const { getRootProps, getInputProps } = useDropzone({ 複数:true、 オンドロップ、 }); // 添付ファイルを削除する const removeFile = file => { const newFiles = [...ファイル] newFiles.splice(newFiles.indexOf(ファイル), 1) setFiles(新しいファイル) } 使用効果(() => { // アップローダーファイルの初期化 ファイルセット([]) },[]) 戻る ( <セクションクラス名="コンテナ"> <div {...getRootProps({className: 'dropzone'})}> <input { ...getInputProps()} /> <p>ファイルをドラッグするかクリックしてファイルを選択してください😊</p> </div> <div className="デモ無限コンテナ"> <無限スクロール 初期ロード={false} ページ開始={0} loadMore={handleInfiniteOnLoad} hasMore={!読み込み中 && hasMore} useWindow={false} を使用します > <リスト データソース={ファイル} レンダリングアイテム={item=> ( <リスト.アイテム アクション={[ // <a key="list-loadmore-edit">編集</a>, <a key="list-loadmore-delete" onClick={removeFile}>削除</a> ]} //追加={ // } キー={アイテムパス}> <リスト.アイテム.メタ アバター={ <> { !!item.type && ['image/gif', 'image/jpeg', 'image/png'].includes(item.type) && <画像 幅={100} alt='ロゴ' src={item.preview} /> } </> } タイトル={item.path} 説明={formatBytes(item.size)} /> </リスト.アイテム> )} > {読み込み中 && hasMore && ( <div className="デモ読み込みコンテナ"> <スピン /> </div> )} </リスト> </無限スクロール> </div> </セクション> ); } Flask コード: 複数のファイルを定義する(): 'files' が request.files にない場合: jsonify({'message': 'ファイルがありません!'}), 200 を返します ファイル = request.files.getlist('ファイル') ファイル内のファイルの場合: ファイルの場合: # secure_filename の中国語問題をピンインで解く filename = secure_filename(''.join(lazy_pinyin(file.filename)) パス(UPLOAD_FOLDER + '/' + file_info['dir_path']).mkdir(parents=True, existing_ok=True) file.save(os.path.join(UPLOAD_FOLDER + '/' + file_info['dir_path'], ファイル名)) return jsonify({'message': '保存に成功しました! !'}) 2. 大きなファイルのインポート: file.slice() メソッドを使用してファイルのチャンクを生成します。 Promise.all は使用しないでください。非連続的なリクエストが発生し、ファイルが破損する可能性があります。 jsコード: const promiseArray = largeFiles.map(file => new Promise((resolve, deny) => { 定数チャンクサイズ = CHUNK_SIZE; const chunks = Math.ceil(file.size / chunkSize); チャンクを 0 にします。 chunkArray = new Array() とします。 while (チャンク <= チャンク) { offset = chunk * chunkSize とします。 スライス = file.slice(オフセット、オフセット+チャンクサイズ) chunkArray.push([スライス, オフセット]) ++チャンク; } const chunkUploadPromises = (スライス、オフセット) => { const largeFileData = 新しい FormData(); largeFileData.append('largeFileData', スライス) 新しい Promise を返します ((resolve, reject) => { アクシオス({ メソッド: 'POST'、 url: '/api/files/largefile', データ: largeFileData、 ヘッダー: { 「コンテンツタイプ」: 「マルチパート/フォームデータ」 } }) .then(応答 => { コンソールログ(応答); 解決する(応答); }) .catch(エラー => { 拒否(エラー); }) }) }; chunkArray.reduce( (前のPromise、[次のChunk、次のOffset]) => { 前のPromise.then(() => { を返します。 chunkUploadPromises(nextChunk, nextOffset) を返します。 }); }, Promise.resolve()); 解決する(); })) Flask コード: ファイル名 = secure_filename(''.join(lazy_pinyin(ファイル名))) パス(UPLOAD_FOLDER + '/' + file_info['dir_path']).mkdir(parents=True, existing_ok=True) save_path = os.path.join(UPLOAD_FOLDER + '/' + file_info['dir_path'], ファイル名) 試す: open(save_path, 'ab') を f として実行します: f.seek(オフセット) f.write(ファイル.ストリーム.read()) print("時間: " + str(datetime.now()) + " オフセット: " + str(オフセット)) OSErrorを除く: return jsonify({'ファイルに書き込めませんでした'}), 500 結論ファイル転送、特に大容量ファイルの転送は、常に HTTP の悩みの種でした。最善の方法は、自分でクライアントを作成し、FTP および FTPS プロトコル経由で転送することです。 2 番目の方法は、大企業の集中型の方法です。ファイルのチェックサムを使用して、ファイルがアップロードされたかどうかを判断し、即時アップロード効果を生み出します。分散型 Bittorrent の 3 番目の方法は、各ユーザーがファイル シードとして機能し、ファイル転送を支援するというものです。これは現在、中国ではあまり使用されていません。 React-Dropzone をベースにしたアップロードコンポーネントの開発に関するこの記事はこれで終わりです。React-Dropzone コンポーネント開発に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: MySQL データベースのデータ テーブルの最適化、外部キーの分析、3 つのパラダイムの使用
>>: Nginx+Keepalived でデュアルマシン マスターとバックアップを実装する方法
ページの主要部分: <body> <ul id="メニュー"&...
イメージを構築するイメージを構築するには、主に 2 つの方法があります。実行中のコンテナをイメージに...
目次序文場合最適化まとめ序文バックエンド開発では、一度に大量のデータがロードされ、メモリやディスク ...
MySQL 6.1.3 をベースにした 8.0.13 をインストールします。 MySQL 8.0....
序文この記事は主に、日常の Web ページ制作で遭遇する問題解決スキルの一部をまとめ、皆さんの参考と...
初心者は自分で録音しましょう1. スーパーバイザーをインストールします。 Supervisor は ...
CentOS 8にDockerをインストールする公式ドキュメント: https://docs.doc...
この記事では、主に html + css を使用してサラウンド リフレクション ローディング エフェ...
マージントップの崩壊とはmargin-top の崩壊は、CSS ボックス モデルで発生する現象です。...
コンテキストの定義と目的コンテキストは、コンポーネント ツリーにプロパティを明示的に渡すことなく、コ...
まず、サーバー環境情報: アンインストールの理由:しばらくするとホストマシンのディスクが100%にな...
目次クラスコンポーネントのプロパティ比較浅い同等の浅い比較機能コンポーネントの簡単な比較先週面接に行...
1. まず、nginxの位置情報に関する関連知識を確認しましょう1) 位置マッチング手順: ~ #波...
目次変数のスコープ閉鎖の概念クロージャの使用クロージャのデメリット最後に、クロージャのメリットとデメ...
私は長い間問題に取り組み、文法上の問題を何度も確認しました。しかし、後でネットで調べてみたら、突然理...