>  기사  >  백엔드 개발  >  전문가처럼 AWS SStream을 사용하여 Go에서 대용량 파일 업로드 처리

전문가처럼 AWS SStream을 사용하여 Go에서 대용량 파일 업로드 처리

Linda Hamilton
Linda Hamilton원래의
2024-10-20 06:08:02259검색

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.