今回は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 でデュアルマシン マスターとバックアップを実装する方法
目次animate() アニメーションメソッドアニメーションキューイングdelay() メソッドアニ...
具体的なコードは次のとおりです。 <a href="#"> <...
目次背景表領域の断片化とは何ですか?表領域の断片化を確認する方法表スペースの断片化問題を解決する方法...
フローティング広告は、ウェブサイト上で非常に一般的な広告形式です。フローティング広告は、ユーザーの閲...
今日は Docker でのネットワーク設定を試し、後で忘れないようにプロセスを記録しました。 (シス...
目次1. はじめに2. 最初の方法3. 2番目の方法要約する1. はじめにVue プロジェクトの開発...
今日、データベース操作はますますアプリケーション全体のパフォーマンスのボトルネックになりつつあり、こ...
目次1. はじめに2. インターフェース3. 簡単な例4. 結論1. はじめにMDN の公式 Web...
PS: ここではPHPStudy2016を使用しています1. 変更中にMySQLを停止する2. my...
この記事では、参考までに、計算機のWebバージョンを実装するためのJavaScriptの具体的なコー...
コードをコピーコードは次のとおりです。 <html> <ヘッド> <ス...
目次ライフサイクル関数一般的なライフサイクルフックVue のインスタンス破棄について:要約するライフ...
1. ファイル名検索を実行するwhich ('実行可能ファイル' を検索) //PA...
VNC はリモート デスクトップ プロトコルです。 VNC を使用して Ubuntu 20.04 を...
目次序文アドバンテージ:欠点: 1. レスポンシブな使用効果2. ステータスが同期されていないRea...