Expo ベースのモバイル アプリでファイルをアップロードおよびダウンロードする方法について、明確な例を見つけるのに苦労しました。同じ課題に直面している他の人、または単に興味がある人を助けるために、私はこの投稿を書きました。
その過程で、理解することが重要な重要な概念を検討していきます。
取り上げる内容:
すべての コード と Postman コレクション は私の GitHub で入手できます。
サーバーは Fastify (Express.js の最新バージョン) で実行されます。アプリを起動するには、次の手順を実行します:
app.js には 3 つの主要なエンドポイントがあります。
fastify.get("/download", async function handler(_, reply) { const fd = await open(FILE_TO_DOWNLOAD); const stream = fd.createReadStream(); const mimeType = mime.lookup(FILE_TO_DOWNLOAD); console.log(`Downloading -> ${FILE_TO_DOWNLOAD}`); return reply .type(mimeType) .header( "Content-Disposition", `attachment; filename=${path.basename(FILE_TO_DOWNLOAD)}` ) .send(stream); });
このエンドポイントは、createReadStream() を使用して、example.webp をストリームとして送信します。 MIME タイプが含まれているため、クライアントはファイルの処理方法を知ることができます。たとえば、.webp の場合、これは image/webp になります。
?注: MIME タイプは、送信されるファイルの形式を定義します。これは、クライアントが正しく表示するのに役立ちます。
その他の MIME タイプを参照してください。
Content-Disposition ヘッダーは、コンテンツがクライアントにどのように表示されるかを定義します。付属品を含む。ファイル名=<ファイル名>ファイルをインラインで表示するのではなく、ダウンロードするようにブラウザーに要求します。直接表示するには、添付ファイルの代わりにインラインを使用します。
Content-Disposition について詳しく学ぶ
fastify.post("/upload-multiples", async function handler(request) { const parts = request.files(); const uploadResults = []; for await (const file of parts) { const fileBuffer = await file.toBuffer(); const filename = file.filename; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, fileBuffer); uploadResults.push({ filename, uploaded: true }); console.log(`Uploaded -> ${filePath}`); } return { uploadedFiles: uploadResults }; });
このエンドポイントはマルチパート/フォームデータリクエストを受け入れます。それ:
たとえば、リクエストは次のようになります:
fastify.get("/download", async function handler(_, reply) { const fd = await open(FILE_TO_DOWNLOAD); const stream = fd.createReadStream(); const mimeType = mime.lookup(FILE_TO_DOWNLOAD); console.log(`Downloading -> ${FILE_TO_DOWNLOAD}`); return reply .type(mimeType) .header( "Content-Disposition", `attachment; filename=${path.basename(FILE_TO_DOWNLOAD)}` ) .send(stream); });
このエンドポイントは、リクエスト本文 (application/octet-stream) に単一のバイナリ ファイルが必要です。 multipart/form-data とは異なり、ファイルはすでにバイナリ データであるため、ディスクに直接書き込むことができます。
Postman ではリクエストは次のようになります:
アプリを実行するには:
Web アプリケーションのすべての機能は App.tsx に含まれています:
この React アプリは 3 つの主要な機能を提供します:
fastify.post("/upload-multiples", async function handler(request) { const parts = request.files(); const uploadResults = []; for await (const file of parts) { const fileBuffer = await file.toBuffer(); const filename = file.filename; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, fileBuffer); uploadResults.push({ filename, uploaded: true }); console.log(`Uploaded -> ${filePath}`); } return { uploadedFiles: uploadResults }; });
ユーザーが「ダウンロード」ボタンをクリックすると、アプリは次のようになります:
動作は、サーバーから返された Content-Disposition ヘッダーによって異なります。
ダウンロードをトリガーするために、アプリは一時的な ファイルを作成します。要素に href を objectURL に設定し、プログラムでクリックして、ユーザーのダウンロード アクションをシミュレートします。
fastify.post("/upload-octet-stream", async function handler(request) { const filename = request.headers["x-file-name"] ?? "unknown.text"; const data = request.body; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, data); return { uploaded: true }; });
「ファイルをアップロード」ボタンをクリックした場合:
これにより、サーバーはアップロードされたファイルを適切に処理し、保存できるようになります。
const downloadFile = async () => { const response = await fetch(DOWNLOAD_API); if (!response.ok) throw new Error("Failed to download file"); const blob = await response.blob(); const contentDisposition = response.headers.get("Content-Disposition"); const isInline = contentDisposition?.split(";")[0] === "inline"; const filename = contentDisposition?.split("filename=")[1]; const url = window.URL.createObjectURL(blob); if (isInline) { window.open(url, "_blank"); } else { const a = document.createElement("a"); a.href = url; a.download = filename || "file.txt"; a.click(); } window.URL.revokeObjectURL(url); };
このアプローチは、multipart/form-data を使用するよりも簡単です。ファイルをバイナリ データとしてリクエスト本文に直接送信し、リクエスト ヘッダーにファイル名を含めるだけです。
次のコマンドでアプリを起動できます:
メイン ロジックは App.tsx にあり、ここで次の内容がレンダリングされます。
fastify.get("/download", async function handler(_, reply) { const fd = await open(FILE_TO_DOWNLOAD); const stream = fd.createReadStream(); const mimeType = mime.lookup(FILE_TO_DOWNLOAD); console.log(`Downloading -> ${FILE_TO_DOWNLOAD}`); return reply .type(mimeType) .header( "Content-Disposition", `attachment; filename=${path.basename(FILE_TO_DOWNLOAD)}` ) .send(stream); });
ファイルを新しいビューで表示するには (ブラウザーが新しいタブでファイルを開く場合と同様)、応答を BLOB として読み取り、FileReader を使用してそれを Base64 に変換する必要があります。
キャッシュ ディレクトリ (アプリのみがアクセスできるプライベート ディレクトリ) にファイルを書き込み、IntentLauncher またはユーザーが iOS を使用している場合は共有を使用してそのファイルを表示します。
fastify.post("/upload-multiples", async function handler(request) { const parts = request.files(); const uploadResults = []; for await (const file of parts) { const fileBuffer = await file.toBuffer(); const filename = file.filename; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, fileBuffer); uploadResults.push({ filename, uploaded: true }); console.log(`Uploaded -> ${filePath}`); } return { uploadedFiles: uploadResults }; });
これは Web プロセスに似ていますが、FileReader を使用して BLOB を Base64 として読み取り、ユーザーがファイルを保存したい場所にファイルをダウンロードする許可を求める必要があります。
fastify.post("/upload-octet-stream", async function handler(request) { const filename = request.headers["x-file-name"] ?? "unknown.text"; const data = request.body; const filePath = path.join(DIR_TO_UPLOAD, filename); await writeFile(filePath, data); return { uploaded: true }; });
DocumentPicker を使用してユーザーがファイルを選択できるようにし、FormData を使用して選択したファイルをリクエストに追加します。プロセスは非常に簡単です。
const downloadFile = async () => { const response = await fetch(DOWNLOAD_API); if (!response.ok) throw new Error("Failed to download file"); const blob = await response.blob(); const contentDisposition = response.headers.get("Content-Disposition"); const isInline = contentDisposition?.split(";")[0] === "inline"; const filename = contentDisposition?.split("filename=")[1]; const url = window.URL.createObjectURL(blob); if (isInline) { window.open(url, "_blank"); } else { const a = document.createElement("a"); a.href = url; a.download = filename || "file.txt"; a.click(); } window.URL.revokeObjectURL(url); };
Application/octet-stream としてアップロードするのは、FormData を使用するよりもさらに簡単です。ヘッダーにファイルの詳細とコンテンツ タイプを設定し、ファイルをリクエスト本文に追加するだけです。
プラットフォーム間でファイルを表示、ダウンロード、アップロードする方法は少しわかりにくいかもしれません。この投稿では最も一般的なものを説明しました。
お役に立てれば幸いです?
@twitter をフォローしてください
以上がReact & Expo - ファイルのアップロードとダウンロード方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。