1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Astro × Cloudflare R2でファイルを配布できる仕組みを作る

Last updated at Posted at 2025-04-26

概要

AstroとCloudflare R2(S3互換ストレージ)を組み合わせてファイルを配布できる仕組みを作ったので、備忘録がてら記事にまとめました。

署名付きURLでセキュアに一時的なダウンロードリンクを発行できるのと、データベースが不要なのでサクッと作れるのが良い点かと思っています。

ただし、大規模なものではなく、ちょっとしたデータ配布をするとき用の構成です。
用途の具体例としては、イベント限定配布や期間限定公開の素材など「数種類だけのデータを手軽に配布したい」ケースを想定しています。

全体の流れ

  1. Cloudflare R2にファイルをアップロード
  2. 環境変数の設定
  3. AstroのAPI Routeで署名付きURLを発行
  4. フロントエンドからAPI Routeを叩き、R2のファイルをダウンロード

Cloudflare R2にファイルをアップロード

Cloudflare R2のバケットを作成し、管理画面やターミナルからファイルをアップロードします。

管理画面からアップロードする場合、作成したバケットのページに行ってアップロードボタンからアップロードするだけです。

詳細は公式ドキュメントをご覧ください。

ターミナルからアップロードする場合、R2はAWS S3互換APIがあるので、AWS CLIを利用できます。

aws s3 cp ./sample.zip s3://your-bucket/your-folder/sample.zip --endpoint-url=https://<your-account-id>.r2.cloudflarestorage.com

こちらも詳細は公式ドキュメントをご覧ください。

AstroのAPI Routeで署名付きURLを発行

AstroのAPI Route(src/pages/api/download/[id].tsといったファイル)で、R2上のファイルに対して「一時的に有効なダウンロードURL」を発行し、リダイレクトします。

import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import type { APIRoute } from "astro";

export const prerender = false;

export const GET: APIRoute = async ({ params, redirect, locals }) => {
  const s3Client = new S3Client({
    region: "auto",
    endpoint: locals.runtime.env.AWS_ENDPOINT,
    credentials: {
      accessKeyId: locals.runtime.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: locals.runtime.env.AWS_SECRET_ACCESS_KEY,
    },
  });

  const command = new GetObjectCommand({
    Bucket: "your-bucket",
    Key: `your-folder/${params.id}.zip`,
  });

  const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 86400 });

  return redirect(signedUrl);
};

署名付きURLで、直リンクを晒さず有効期限付きで安全に配布できます。
また先ほども記載したとおりS3互換なので、AWS SDKがそのまま使えます。

環境変数の設定

.dev.varsに環境変数を設定します。

AWS_ENDPOINT=https://<your-account-id>.r2.cloudflarestorage.com
AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

それぞれの値の取得の方法は公式ドキュメントを確認してください。

フロントエンドからAPI Routeを叩き、R2のファイルをダウンロード

Astroのページ内で、API Routeへのリンクをダウンロードボタンとして設置します。

src/pages/[id].astro
---
import { getCollection } from "astro:content";
import type { APIRoute } from "astro";

export async function getStaticPaths() {
  const items = await getCollection("exampleCollection");
  return items.map((item) => ({
    params: { id: item.id },
    props: { item },
  }));
}

const { item } = Astro.props;
---

<a
  download
  href={`/api/download/${item.id}`}
>
  ダウンロード
</a>

まとめ

  • Astro × Cloudflare R2で、サーバーレスでセキュアにファイルを配布できる仕組みが作れる
  • データベース不要、運用コストも最小限
  • 署名付きURLで安全に配布できるので、素材配布や限定ファイルの配布にも最適
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?