ホームページ >ウェブフロントエンド >jsチュートリアル >React & Expo - ファイルのアップロードとダウンロード方法

React & Expo - ファイルのアップロードとダウンロード方法

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-16 00:30:14580ブラウズ

導入

Expo ベースのモバイル アプリでファイルをアップロードおよびダウンロードする方法について、明確な例を見つけるのに苦労しました。同じ課題に直面している他の人、または単に興味がある人を助けるために、私はこの投稿を書きました。

その過程で、理解することが重要な重要な概念を検討していきます。

  • バッファ
  • インテントフィルター
  • MIME タイプ
  • アプリケーション/オクテットストリーム
  • マルチパート/フォームデータ
  • さらに...

取り上げる内容:

  • Fastify サーバーとのファイルの送受信。
  • React Web アプリでのファイルのアップロード、ダウンロード、表示。
  • React Native (Expo) モバイル アプリでのファイルのアップロード、ダウンロード、表示。

すべての コードPostman コレクション は私の GitHub で入手できます。

サーバ

React & Expo - How to Upload & Download Files

サーバーは Fastify (Express.js の最新バージョン) で実行されます。アプリを起動するには、次の手順を実行します:

  1. ターミナルを使用して /server に移動します
  2. npm install を使用して依存関係をインストールします
  3. npm run dev を使用してサーバーを実行します

app.js には 3 つの主要なエンドポイントがあります。

- ダウンロードエンドポイント (/download)

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 について詳しく学ぶ

React & Expo - How to Upload & Download Files

- フォームデータを使用して複数のファイルをアップロード (/upload-multiples)

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 };
});

このエンドポイントはマルチパート/フォームデータリクエストを受け入れます。それ:

  1. リクエストからファイルを取得します。
  2. 各ファイルをバッファ (バイナリ データの JavaScript 表現) に変換します。
  3. ファイルを /upload ディレクトリに保存します。

たとえば、リクエストは次のようになります:

React & Expo - How to Upload & Download Files

- Octet Stream (/upload-octet-stream) を使用したファイルのアップロード

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 ではリクエストは次のようになります:

React & Expo - How to Upload & Download Files

React & Expo - How to Upload & Download Files

ウェブ (反応)



React & Expo - How to Upload & Download Files

アプリを実行するには:

  1. ターミナルを使用して /web に移動します
  2. npm install を使用して依存関係をインストールします
  3. npm run dev を使用してアプリを起動します

Web アプリケーションのすべての機能は App.tsx に含まれています:

React & Expo - How to Upload & Download Files

この 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 };
});

ユーザーが「ダウンロード」ボタンをクリックすると、アプリは次のようになります:

  1. /download エンドポイントを呼び出します。
  2. ファイルをバイナリ BLOB として受信します。
  3. BLOB から objectURL を作成し、ブラウザーがアクセスできる一時 URL として機能します。

動作は、サーバーから返された Content-Disposition ヘッダーによって異なります。

  • 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 };
});

「ファイルをアップロード」ボタンをクリックした場合:

  1. uploadFile 関数が実行され、非表示の が作成されます。要素を追加し、ユーザーのクリックをシミュレートします。
  2. ユーザーが 1 つ以上のファイルを選択すると、それらのファイルは FormData オブジェクトに追加されます。
  3. リクエストは /upload-multiples エンドポイントに送信され、multipart/form-data 経由でファイルを受け取ります。

これにより、サーバーはアップロードされたファイルを適切に処理し、保存できるようになります。

- Octet Streamを使用したファイルのアップロード

  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 を使用するよりも簡単です。ファイルをバイナリ データとしてリクエスト本文に直接送信し、リクエスト ヘッダーにファイル名を含めるだけです。

モバイル(エキスポ)



React & Expo - How to Upload & Download Files

次のコマンドでアプリを起動できます:

  1. 端末のモバイル ディレクトリに移動します。
  2. 依存関係をインストールします: npm install
  3. npm run android または npm run ios でプロジェクトを実行します

メイン ロジックは 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。