ホームページ >バックエンド開発 >Golang >AWS SStream を使用して Go で大規模ファイルのアップロードをプロのように処理する

AWS SStream を使用して Go で大規模ファイルのアップロードをプロのように処理する

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-20 06:08:02351ブラウズ

Handling Large File Uploads in Go with AWS SStream Like a Pro

前の投稿では、ローカル ストレージを備えた Go とクラウドベースのストレージに Amazon S3 を使用してファイル アップロード サービスを構築しました。しかし、大きなファイル、つまり数ギガバイトのビデオ ファイルやデータセットを処理する必要がある場合はどうすればよいでしょうか? ?そこが難しいところです。サーバーが停止したり、メモリが不足したりすることは望ましくありません。

この投稿では、AWS S3 でストリーミングチャンキングを使用して大きなファイルのアップロードを効率的に処理する方法を検討します。こうすることで、最大のファイルでもアプリが機能不全に陥ることはありません。

ここで取り上げる内容は次のとおりです:

  1. 大きなファイルの処理に特別な注意が必要な理由
  2. メモリ使用量を最小限に抑えながら、大きなファイルを S3 に直接ストリーミングします。
  3. 大きなファイルをチャンク化し、S3 上で再組み立てします。
  4. 実稼働環境での大きなファイルのアップロードのベスト プラクティス。

大きなファイルをクラウドに送信する準備はできていますか?飛び込んでみましょう! ?️


ステップ 1: 大きなファイルの処理が異なる理由

大きなファイルのアップロードを扱う場合、ファイル全体をメモリにロードすることは絶対に避けてください。ファイルが小さい場合、これは大した問題ではありませんが、ファイルが大きい場合、特に複数の同時アップロードを処理する場合、すぐにサーバーのメモリの制限に達します。

ストリーミングチャンキング は、これらの大きなファイルを効率的に処理できるようにする重要なテクニックです。

  • ストリーミング: ファイル全体をメモリにロードするのではなく、サーバーが受信するときにファイルを S3 にアップロードします。
  • チャンク: 大きなファイルを小さな部分 (チャンク) に分割し、各チャンクを個別にアップロードします。これは、失敗したアップロードを再開する場合や、並行してアップロードする場合に特に便利です。

ステップ 2: 大きなファイルを S3 に直接ストリーミングする

AWS SDK を使用して、ユーザーのアップロードリクエストから直接 S3 にファイルをストリーミングし、サーバー上で必要なメモリ量を最小限に抑えます。

アップロードハンドラーの更新

S3 にアップロードする前にファイル全体をメモリまたはディスクに保存する代わりに、ストリーム を使用してファイルをリアルタイムで送信できます。既存の fileUploadHandler を変更して、大きなファイルをより効率的に処理しましょう。

import (
    "fmt"
    "io"
    "net/http"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func fileUploadHandler(w http.ResponseWriter, r *http.Request) {
    // Limit the request size (e.g., 10GB max size)
    r.Body = http.MaxBytesReader(w, r.Body, 10<<30)

    // Parse the multipart form data
    err := r.ParseMultipartForm(10 << 20)
    if err != nil {
        http.Error(w, "File too large", http.StatusRequestEntityTooLarge)
        return
    }

    // Retrieve the file from the form
    file, handler, err := r.FormFile("file")
    if err != nil {
        http.Error(w, "Error retrieving file", http.StatusBadRequest)
        return
    }
    defer file.Close()

    // Set up AWS session
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("us-west-1"),
    })
    if err != nil {
        http.Error(w, "Error connecting to AWS", http.StatusInternalServerError)
        return
    }

    // Create the S3 client
    s3Client := s3.New(sess)

    // Stream the file directly to S3
    _, err = s3Client.PutObject(&s3.PutObjectInput{
        Bucket: aws.String("your-bucket-name"),
        Key:    aws.String(handler.Filename),
        Body:   file, // Stream the file directly from the request
        ACL:    aws.String("public-read"),
    })
    if err != nil {
        http.Error(w, "Error uploading file to S3", http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "File uploaded successfully to S3!")
}

このアプローチでは、ファイルはリクエストから S3 に直接ストリーミングされるため、ファイル全体をメモリに保存する必要がなく、大きなファイルにとっては救世主となります。


ステップ 3: 大きなファイルをチャンク化する

さらに一歩進めたい場合は、クライアント側でファイルを チャンク に分割し、より小さな部分にアップロードできます。これは、アップロードを最初からやり直すのが面倒な、不安定な接続や巨大なファイルを処理する場合に特に便利です。

クライアント側のチャンク化の例

クライアント側で、ファイルを小さなチャンクに分割し、それぞれを個別にアップロードします。以下は JavaScript を使用した例です:

import (
    "fmt"
    "io"
    "net/http"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func fileUploadHandler(w http.ResponseWriter, r *http.Request) {
    // Limit the request size (e.g., 10GB max size)
    r.Body = http.MaxBytesReader(w, r.Body, 10<<30)

    // Parse the multipart form data
    err := r.ParseMultipartForm(10 << 20)
    if err != nil {
        http.Error(w, "File too large", http.StatusRequestEntityTooLarge)
        return
    }

    // Retrieve the file from the form
    file, handler, err := r.FormFile("file")
    if err != nil {
        http.Error(w, "Error retrieving file", http.StatusBadRequest)
        return
    }
    defer file.Close()

    // Set up AWS session
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("us-west-1"),
    })
    if err != nil {
        http.Error(w, "Error connecting to AWS", http.StatusInternalServerError)
        return
    }

    // Create the S3 client
    s3Client := s3.New(sess)

    // Stream the file directly to S3
    _, err = s3Client.PutObject(&s3.PutObjectInput{
        Bucket: aws.String("your-bucket-name"),
        Key:    aws.String(handler.Filename),
        Body:   file, // Stream the file directly from the request
        ACL:    aws.String("public-read"),
    })
    if err != nil {
        http.Error(w, "Error uploading file to S3", http.StatusInternalServerError)
        return
    }

    fmt.Fprintf(w, "File uploaded successfully to S3!")
}

サーバー側でのチャンクの処理

サーバー側では、これらのチャンクを受信し、S3 に保存されているファイルに追加できます:

async function uploadFileInChunks(file) {
  const chunkSize = 5 * 1024 * 1024; // 5MB per chunk
  const totalChunks = Math.ceil(file.size / chunkSize);

  for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(file.size, start + chunkSize);
    const chunk = file.slice(start, end);

    const formData = new FormData();
    formData.append("chunk", chunk);
    formData.append("chunkIndex", i);
    formData.append("filename", file.name);

    await fetch("/upload-chunk", {
      method: "POST",
      body: formData,
    });
  }
}

この方法では、ファイルのチャンクを個別にアップロードし、それらをクラウドにマージできます。信頼性が重要な非常に大規模なアップロードを処理するのに最適です。


ステップ 4: 大きなファイルのアップロードのベスト プラクティス

  1. リクエスト サイズの制限: ユーザーがサーバーを圧迫しないように、常に適切な最大リクエスト サイズ (MaxBytesReader) を設定します。

  2. S3 のマルチパート アップロード: AWS S3 は、大きなファイルに最適な マルチパート アップロード をサポートしています。パーツを並行してアップロードしたり、失敗したアップロードを再開したりすることもできます。

  3. 安全なファイル アップロード: ファイルの種類を検証し、ファイルのアップロードには安全な接続 (HTTPS) を使用してください。ファイル名をサニタイズして、ディレクトリ トラバーサル攻撃を防ぎます。

  4. 進行状況インジケーター: ファイルをチャンク化している場合、特に大きなファイルのユーザー エクスペリエンスを向上させるために、進行状況インジケーターを実装します。


まとめ

大きなファイルのアップロードの処理に頭を悩ませる必要はありません。 Go と S3 でストリーミングおよびチャンク技術を使用すると、サーバーのメモリを消費することなく、最大のファイルでも効率的に管理できます。ファイル ストレージ サービス、ビデオ プラットフォーム、メディアを多用するアプリのいずれを構築している場合でも、プロのように大量のアップロードを処理できるようになりました。 ?

プロジェクトに大きなファイルのアップロードを実装しましたか? あなたの経験やヒントをコメントに書き込んで、会話を続けましょう。 ?

以上がAWS SStream を使用して Go で大規模ファイルのアップロードをプロのように処理するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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