首頁  >  文章  >  後端開發  >  像專業人士一樣使用 A​​WS SStream 在 Go 中處理大檔案上傳

像專業人士一樣使用 A​​WS SStream 在 Go 中處理大檔案上傳

Linda Hamilton
Linda Hamilton原創
2024-10-20 06:08:02349瀏覽

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,從而最大限度地減少伺服器上所需的記憶體量。

更新上傳處理程序

我們可以使用 streams 即時發送文件,而不是在將整個文件上傳到 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 結合使用,您甚至可以有效地管理最大的文件,而不會佔用伺服器的記憶體。無論您是建立文件儲存服務、影片平台還是媒體密集型應用程序,您現在都可以像專業人士一樣處理大量上傳。 ?

您在專案中實作過大檔案上傳嗎? 在評論中留下您的經驗或技巧,讓我們繼續對話! ?

以上是像專業人士一樣使用 A​​WS SStream 在 Go 中處理大檔案上傳的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn