이전 게시물에서는 로컬 스토리지인 Go와 클라우드 기반 스토리지인 Amazon S3를 사용하여 파일 업로드 서비스를 구축했습니다. 하지만 대용량 파일을 처리해야 한다면 어떻게 해야 할까요? 수 기가바이트급 비디오 파일이나 데이터세트를 생각해보세요. ? 상황이 까다로워질 수 있는 곳이 바로 여기입니다. 서버가 다운되거나 메모리가 부족해지는 것을 원하지 않습니다.
이 게시물에서는 AWS 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으로 직접 스트리밍되므로 전체 파일을 메모리에 저장하지 않으므로 대용량 파일의 구원자가 됩니다!
한 단계 더 나아가고 싶다면 클라이언트 측에서 파일을 청크로 나누고 더 작은 조각으로 업로드할 수 있습니다. 이는 업로드를 처음부터 다시 시작하는 것이 어려울 수 있는 불안정한 연결이나 대용량 파일을 처리하는 데 특히 유용합니다.
클라이언트 측에서는 파일을 더 작은 덩어리로 나누고 각각을 별도로 업로드합니다. 다음은 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, }); } }
이 방법을 사용하면 파일 덩어리를 독립적으로 업로드하고 클라우드에서 병합할 수 있습니다. 안정성이 중요한 대규모 업로드를 처리하는 데 적합합니다.
요청 크기 제한: 사용자가 서버에 부담을 주지 않도록 항상 합리적인 최대 요청 크기(MaxBytesReader)를 설정하세요.
S3용 멀티파트 업로드: AWS S3는 대용량 파일에 이상적인 멀티파트 업로드를 지원합니다. 여러 부분을 동시에 업로드할 수 있으며 실패한 업로드를 재개할 수도 있습니다.
보안 파일 업로드: 파일 형식을 확인하고 파일 업로드에 보안 연결(HTTPS)을 사용하는지 확인하세요. 디렉토리 순회 공격을 방지하려면 파일 이름을 삭제하세요.
진행률 표시기: 파일을 청크하는 경우 특히 대용량 파일의 경우 더 나은 사용자 환경을 위해 진행률 표시기를 구현하세요.
대용량 파일 업로드를 처리하는 것이 골치 아픈 일이 될 필요는 없습니다. Go 및 S3와 함께 스트리밍 및 청킹 기술을 사용하면 서버 메모리를 소모하지 않고도 가장 큰 파일도 효율적으로 관리할 수 있습니다. 파일 저장 서비스, 비디오 플랫폼, 미디어 중심 앱 등 무엇을 구축하든 이제 전문가처럼 대규모 업로드를 처리할 수 있습니다. ?
프로젝트에 대용량 파일 업로드를 구현하셨나요? 댓글에 경험이나 팁을 남겨주시고 대화를 계속 이어가세요! ?
위 내용은 전문가처럼 AWS SStream을 사용하여 Go에서 대용량 파일 업로드 처리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!