0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

署名付きURLを生成して、ブラウザから直接GCSにアップロードする

Posted at

はじめに

ブラウザからサイズの大きいファイルをアップロードしようとした際にCloud Runの容量制限を越えられないため、GCSから署名つきURLを発行してブラウザから直接アップロードしました。

開発環境

  • Next.js 14.2.2
  • Terraform
  • Cloud Run (実行環境)

署名付きURLの発行

index.ts
export async function getSignedUrl(): Promise<string> {
  try {
    const filePath = "filename.wav";
    const storage = new Storage();
    const file = storage
      .bucket("your_bucket_name")
      .file(filePath);
    const [signedUrl] = await file.getSignedUrl({
      version: "v4",
      action: "write",
      expires: Date.now() + 24 * 60 * 60 * 1000, // 24 hours
    });

    return signedUrl;
  } catch (error) {
    console.error(error);
    throw new Error("Failed to get signed URL");
  }
}

ブラウザ側からGCSにアップロード

async function uploadDataToGCS(): Promise<string> {
  try {
    const signedUrl = await getSignedUrl(encodedFileName);
    await fetch(signedUrl, {
      method: "PUT",
      body: value,
    });
  } catch (error) {
    console.error("Error upload file to GCS:", error);
  }
}

CORSの設定をしていない場合はエラーになります。必ず設定しましょう。

実際はterraformで実装してますが、動作確認などローカル環境で実行させるにはコンソール、もしくはscriptで直接設定しても良いかもしれません。

storage_bucket.tf
resource "google_storage_bucket" "asset_bucket" {
  name          = "your-asset-bucket-name"
  location      = "US"
  force_destroy = true

  cors {
    origin          = ["http://localhost:3000"]
    method          = ["PUT"]
    response_header = ["Content-Type"]
    max_age_seconds = 3600
  }
}
async function configureBucketCors() {
  await storage.bucket(bucketName).setCorsConfiguration([
    {
      maxAgeSeconds,
      method: [method],
      origin: [origin],
      responseHeader: [responseHeader],
    },
  ]);
}

サービスアカウントの権限の設定

権限設定もコンソールから設定できますが、実際はprod,stg,dev等の環境があるはずです。毎回コンソールから設定していてはミスしかねないので、このようにインフラもコード化しておきましょう!

service_account.tf
resource "google_project_iam_member" "service_account_sign_blob" {
  project = "<YOUR_PROJECT_ID>"
  role    = "roles/iam.serviceAccountTokenCreator"
  member  = "serviceAccount:${google_service_account.my_service_account.email}"
}
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?