ホームページ  >  記事  >  ウェブフロントエンド  >  大きなファイルのアップロードの最適化: AWS S3 への安全なクライアント側マルチパート アップロード

大きなファイルのアップロードの最適化: AWS S3 への安全なクライアント側マルチパート アップロード

Susan Sarandon
Susan Sarandonオリジナル
2024-11-08 07:22:02388ブラウズ

大きなファイルをクラウドにアップロードするのは困難な場合があります。ネットワークの中断、ブラウザの制限、および巨大なファイル サイズにより、プロセスが簡単に中断される可能性があります。 Amazon S3 (Simple Storage Service) は、データとアプリケーションのオンライン バックアップとアーカイブ用に設計された、スケーラブルで高速な Web ベースのクラウド ストレージ サービスです。ただし、大きなファイルを S3 にアップロードするには、信頼性とパフォーマンスを確保するために慎重な取り扱いが必要です。

AWS S3 のマルチパート アップロードをご利用ください。これは、大きなファイルを小さなチャンクに分割し、各パートを個別に処理し、パートを並行してアップロードすることで、より高速で信頼性の高いアップロードを可能にする強力なソリューションです。この方法は、ファイル サイズの制限 (S3 では 5 GB を超えるファイルのマルチパート アップロードが必要です) を克服するだけでなく、失敗のリスクも最小限に抑えるため、シームレスで堅牢なファイル アップロードを必要とするアプリケーションに最適です。

このガイドでは、S3 へのクライアント側のマルチパート アップロードの詳細を明らかにし、大きなファイルを処理する場合に S3 が賢明な選択である理由、安全に起動して実行する方法、注意すべき課題を示します。のために出かけます。信頼性の高いクライアント側のファイル アップロード ソリューションの実装に役立つ、段階的な手順、コード例、ベスト プラクティスを提供します。

ファイルのアップロード エクスペリエンスをアップグレードする準備はできていますか?飛び込んでみましょう!

サーバー側とクライアント側のアップロード

ファイル アップロード システムを設計する場合、サーバー経由でファイルをアップロードする (サーバー側) か、クライアントから S3 にファイルを直接アップロードする (クライアント側) という 2 つの主なオプションがあります。それぞれのアプローチには長所と短所があります。

サーバー側のアップロード

Optimizing Large File Uploads: Secure Client-Side Multipart Uploads to AWS S3

長所:

  • セキュリティの強化: すべてのアップロードはサーバーによって管理され、AWS 認証情報を安全に保ちます。

  • エラー処理の改善: サーバーは再試行、ログ記録、エラー処理をより堅牢に管理できます。

  • 集中処理: ファイルは S3 に保存する前にサーバー上で検証、処理、または変換できます。

短所:

  • サーバー負荷の増加: 大規模なアップロードはサーバー リソース (CPU、メモリ、帯域幅) を消費し、パフォーマンスに影響を与え、運用コストを増加させる可能性があります。

  • 潜在的なボトルネック: アップロード トラフィックが多い場合、サーバーが単一障害点またはパフォーマンスのボトルネックとなり、アップロードの遅延やダウンタイムにつながる可能性があります。

  • コストの増加: サーバー側でアップロードを処理するには、ピーク負荷に対処するためにインフラストラクチャの拡張が必要になる場合があり、運用コストが増加します。

クライアント側のアップロード

Optimizing Large File Uploads: Secure Client-Side Multipart Uploads to AWS S3

長所:

  • サーバー負荷の軽減: ファイルはユーザーのデバイスから S3 に直接送信され、サーバー リソースが解放されます。

  • 速度の向上: アプリケーション サーバーをバイパスするため、ユーザーはより高速なアップロードを体験できます。

  • コスト効率: 大規模なアップロードを処理するためのサーバー インフラストラクチャの必要性がなくなり、コストが削減される可能性があります。

  • スケーラビリティ: バックエンド サーバーにストレスを与えずにファイルのアップロードを拡張するのに最適です。

短所:

  • セキュリティリスク: AWS 認証情報と権限を慎重に扱う必要があります。署名付き URL は、不正アクセスを防ぐために安全に生成される必要があります。

  • 制限された制御: アップロードに対するサーバー側の監視が少なくなります。エラー処理と再試行は多くの場合クライアントで管理されます。

  • ブラウザの制約: ブラウザにはメモリと API の制限があり、非常に大きなファイルの処理が妨げられたり、ローエンド デバイスのパフォーマンスに影響を与えたりする可能性があります。

安全なクライアント側アップロードを実装するためのステップバイステップ ガイド

クライアント側のアップロードを安全に実装するには、フロントエンド アプリケーションと安全なバックエンド サービスの間の調整が必要です。バックエンド サービスの主な役割は、署名付き URL を生成し、クライアントが機密の AWS 認証情報を公開せずにファイルを S3 に直接アップロードできるようにすることです。

前提条件

  • AWS アカウント: S3 を使用する権限を持つ AWS アカウントへのアクセス。
  • AWS SDK の知識: AWS SDK for JavaScript (v3) に関する知識、または AWS サービスへの直接 API 呼び出しの実行。
  • フロントエンドおよびバックエンドの開発スキル: クライアント側 (JavaScript、React など) とサーバー側 (Node.js、Express など) の両方のプログラミングについての理解

1. 適切なアーキテクチャのセットアップ

クライアント側のアップロードを効果的に実装するには、以下が必要です。

  • フロントエンド アプリケーション: ファイルの選択を処理し、必要に応じてファイルをパーツに分割し、署名付き URL を使用してパーツを S3 にアップロードします。
  • バックエンド サービス: 署名付き URL を生成し、マルチパート アップロードを初期化または完了するための API を提供する安全なサーバー。 AWS 認証情報を安全に保ち、必要なビジネス ロジックや検証を強制します。

このアーキテクチャにより、フロントエンドがアップロード プロセスを管理しながら、機密性の高い操作がバックエンドで安全に処理されることが保証されます。

2. バックエンドでのアップロード サービスの作成

署名付き URL を使用する理由

署名付き URL を使用すると、クライアントは S3 と直接対話でき、クライアント側で AWS 認証情報を必要とせずにファイルのアップロードなどの操作を実行できます。これらは次の理由で安全です:

  • 時間制限があり、指定された期間が経過すると期限切れになります。
  • 特定の操作 (アップロードのための PUT など) に制限できます。
  • これらは、特定の S3 オブジェクト キーに固有です。

S3UploadServiceの実装

サーバー上に以下を担当するサービス クラスを作成します。

a. S3 バケットとリージョンの定義
b. AWS 認証情報を安全に確立します。
c.署名付き URL を生成し、マルチパート アップロードを管理するメソッドを提供します。

// services/S3UploadService.js

import {
  S3Client,
  CreateMultipartUploadCommand,
  CompleteMultipartUploadCommand,
  UploadPartCommand,
  AbortMultipartUploadCommand,
  PutObjectCommand,
  GetObjectCommand,
  DeleteObjectCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

// Import credential providers
import {
  fromIni,
  fromInstanceMetadata,
  fromEnv,
  fromProcess,
} from '@aws-sdk/credential-providers';

export class S3UploadService {
  constructor() {
    this.s3BucketName = process.env.S3_BUCKET_NAME;
    this.s3Region = process.env.S3_REGION;

    this.s3Client = new S3Client({
      region: this.s3Region,
      credentials: this.getS3ClientCredentials(),
    });
  }

  // Method to generate AWS credentials securely
  getS3ClientCredentials() {
    if (process.env.NODE_ENV === 'development') {
      // In development, use credentials from environment variables
      return fromEnv();
    } else {
      // In production, use credentials from EC2 instance metadata or another secure method
      return fromInstanceMetadata();
    }
  }

  // Generate a presigned URL for single-part upload (PUT), download (GET), or deletion (DELETE)
  async generatePresignedUrl(key, operation) {
    let command;
    switch (operation) {
      case 'PUT':
        command = new PutObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      case 'GET':
        command = new GetObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      case 'DELETE':
        command = new DeleteObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      default:
        throw new Error(`Invalid operation "${operation}"`);
    }

    // Generate presigned URL
    return await getSignedUrl(this.s3Client, command, { expiresIn: 3600 }); // Expires in 1 hour
  }

  // Methods for multipart upload
  async createMultipartUpload(key) {
    const command = new CreateMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
    });
    const response = await this.s3Client.send(command);
    return response.UploadId;
  }

  async generateUploadPartUrl(key, uploadId, partNumber) {
    const command = new UploadPartCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
      PartNumber: partNumber,
    });

    return await getSignedUrl(this.s3Client, command, { expiresIn: 3600 });
  }

  async completeMultipartUpload(key, uploadId, parts) {
    const command = new CompleteMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
      MultipartUpload: { Parts: parts },
    });
    return await this.s3Client.send(command);
  }

  async abortMultipartUpload(key, uploadId) {
    const command = new AbortMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
    });
    return await this.s3Client.send(command);
  }
}

: AWS 認証情報が安全に管理されていることを確認してください。本番環境では、認証情報をハードコーディングしたり環境変数を使用したりするのではなく、EC2 インスタンスまたは ECS タスクにアタッチされた IAM ロールを使用することをお勧めします。

3. バックエンド API エンドポイントの実装

フロントエンドからのリクエストを処理するために、バックエンドに API エンドポイントを作成します。これらのエンドポイントは、S3UploadService を利用してアクションを実行します。

// controllers/S3UploadController.js

import { S3UploadService } from '../services/S3UploadService';

const s3UploadService = new S3UploadService();

export const generatePresignedUrl = async (req, res, next) => {
  try {
    const { key, operation } = req.body; // key is the S3 object key (file identifier)
    const url = await s3UploadService.generatePresignedUrl(key, operation);
    res.status(200).json({ url });
  } catch (error) {
    next(error);
  }
};

export const initializeMultipartUpload = async (req, res, next) => {
  try {
    const { key } = req.body;
    const uploadId = await s3UploadService.createMultipartUpload(key);
    res.status(200).json({ uploadId });
  } catch (error) {
    next(error);
  }
};

export const generateUploadPartUrls = async (req, res, next) => {
  try {
    const { key, uploadId, parts } = req.body; // parts is the number of parts
    const urls = await Promise.all(
      [...Array(parts).keys()].map(async (index) => {
        const partNumber = index + 1;
        const url = await s3UploadService.generateUploadPartUrl(key, uploadId, partNumber);
        return { partNumber, url };
      })
    );
    res.status(200).json({ urls });
  } catch (error) {
    next(error);
  }
};

export const completeMultipartUpload = async (req, res, next) => {
  try {
    const { key, uploadId, parts } = req.body; // parts is an array of { ETag, PartNumber }
    const result = await s3UploadService.completeMultipartUpload(key, uploadId, parts);
    res.status(200).json({ result });
  } catch (error) {
    next(error);
  }
};

export const abortMultipartUpload = async (req, res, next) => {
  try {
    const { key, uploadId } = req.body;
    await s3UploadService.abortMultipartUpload(key, uploadId);
    res.status(200).json({ message: 'Upload aborted' });
  } catch (error) {
    next(error);
  }
};

Express アプリまたは使用しているフレームワークでこれらのエンドポイントのルートを設定します。

4. フロントエンド アップローダー クラスの実装

フロントエンドは、ファイルの選択、ファイル サイズに基づいてシングルパート アップロードを実行するかマルチパート アップロードを実行するかを決定し、アップロード プロセスを管理します。

一般に、AWS は「オブジェクトのサイズが 100 MB に達した場合、オブジェクトを 1 回の操作でアップロードするのではなく、マルチパート アップロードの使用を検討する必要があります。」と推奨しています。ソース

// services/S3UploadService.js

import {
  S3Client,
  CreateMultipartUploadCommand,
  CompleteMultipartUploadCommand,
  UploadPartCommand,
  AbortMultipartUploadCommand,
  PutObjectCommand,
  GetObjectCommand,
  DeleteObjectCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

// Import credential providers
import {
  fromIni,
  fromInstanceMetadata,
  fromEnv,
  fromProcess,
} from '@aws-sdk/credential-providers';

export class S3UploadService {
  constructor() {
    this.s3BucketName = process.env.S3_BUCKET_NAME;
    this.s3Region = process.env.S3_REGION;

    this.s3Client = new S3Client({
      region: this.s3Region,
      credentials: this.getS3ClientCredentials(),
    });
  }

  // Method to generate AWS credentials securely
  getS3ClientCredentials() {
    if (process.env.NODE_ENV === 'development') {
      // In development, use credentials from environment variables
      return fromEnv();
    } else {
      // In production, use credentials from EC2 instance metadata or another secure method
      return fromInstanceMetadata();
    }
  }

  // Generate a presigned URL for single-part upload (PUT), download (GET), or deletion (DELETE)
  async generatePresignedUrl(key, operation) {
    let command;
    switch (operation) {
      case 'PUT':
        command = new PutObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      case 'GET':
        command = new GetObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      case 'DELETE':
        command = new DeleteObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      default:
        throw new Error(`Invalid operation "${operation}"`);
    }

    // Generate presigned URL
    return await getSignedUrl(this.s3Client, command, { expiresIn: 3600 }); // Expires in 1 hour
  }

  // Methods for multipart upload
  async createMultipartUpload(key) {
    const command = new CreateMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
    });
    const response = await this.s3Client.send(command);
    return response.UploadId;
  }

  async generateUploadPartUrl(key, uploadId, partNumber) {
    const command = new UploadPartCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
      PartNumber: partNumber,
    });

    return await getSignedUrl(this.s3Client, command, { expiresIn: 3600 });
  }

  async completeMultipartUpload(key, uploadId, parts) {
    const command = new CompleteMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
      MultipartUpload: { Parts: parts },
    });
    return await this.s3Client.send(command);
  }

  async abortMultipartUpload(key, uploadId) {
    const command = new AbortMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
    });
    return await this.s3Client.send(command);
  }
}

使用例

// controllers/S3UploadController.js

import { S3UploadService } from '../services/S3UploadService';

const s3UploadService = new S3UploadService();

export const generatePresignedUrl = async (req, res, next) => {
  try {
    const { key, operation } = req.body; // key is the S3 object key (file identifier)
    const url = await s3UploadService.generatePresignedUrl(key, operation);
    res.status(200).json({ url });
  } catch (error) {
    next(error);
  }
};

export const initializeMultipartUpload = async (req, res, next) => {
  try {
    const { key } = req.body;
    const uploadId = await s3UploadService.createMultipartUpload(key);
    res.status(200).json({ uploadId });
  } catch (error) {
    next(error);
  }
};

export const generateUploadPartUrls = async (req, res, next) => {
  try {
    const { key, uploadId, parts } = req.body; // parts is the number of parts
    const urls = await Promise.all(
      [...Array(parts).keys()].map(async (index) => {
        const partNumber = index + 1;
        const url = await s3UploadService.generateUploadPartUrl(key, uploadId, partNumber);
        return { partNumber, url };
      })
    );
    res.status(200).json({ urls });
  } catch (error) {
    next(error);
  }
};

export const completeMultipartUpload = async (req, res, next) => {
  try {
    const { key, uploadId, parts } = req.body; // parts is an array of { ETag, PartNumber }
    const result = await s3UploadService.completeMultipartUpload(key, uploadId, parts);
    res.status(200).json({ result });
  } catch (error) {
    next(error);
  }
};

export const abortMultipartUpload = async (req, res, next) => {
  try {
    const { key, uploadId } = req.body;
    await s3UploadService.abortMultipartUpload(key, uploadId);
    res.status(200).json({ message: 'Upload aborted' });
  } catch (error) {
    next(error);
  }
};

5. セキュリティに関する考慮事項とベストプラクティス

  • 署名付き URL の権限を制限する: 署名付き URL が必要な権限のみを付与するようにします (アップロードの PUT 操作のみを許可するなど)。
  • 適切な有効期限を設定する: 署名付き URL は、悪用される可能性を最小限に抑えるために、適切な時間 (例: 15 分から 1 時間) 後に期限切れになる必要があります。
  • ファイル メタデータの検証: バックエンドで、クライアントから送信されたメタデータまたはパラメーターを検証して、操作を防止します (例: 許可されたファイル タイプまたはサイズを強制する)。
  • HTTPS を使用する: クライアントとバックエンド間の通信、および S3 にアクセスする場合は、転送中のデータを保護するために、常に HTTPS を使用します。
  • 監視とログ: バックエンドと S3 の両方にログと監視を実装して、異常なアクティビティやエラーを検出します。

6. 追加の考慮事項

オブジェクトサイズの制限

AWS S3 は最大 5 TiB (テラバイト) のサイズのオブジェクトをサポートしますが、そのような大規模なファイルをブラウザから直接アップロードすることは非現実的であり、ブラウザの制限やクライアント側のリソースの制約により不可能なことがよくあります。非常に大きなファイルを処理するとき、特にファイルをメモリ内で処理する必要がある場合、ブラウザがクラッシュしたり応答しなくなったりすることがあります。

おすすめ:
  • 実用的な制限の設定: アプリケーションがクライアント側アップロードでサポートする最大ファイル サイズを定義します (例: 100 GB 以下)。
  • ユーザーに通知: アップロードを開始する前に、許可される最大ファイル サイズについてユーザーにフィードバックを提供し、クライアント側で検証を処理します。

再試行戦略

大きなファイルをアップロードすると、アップロード プロセス中にネットワークの中断や障害が発生するリスクが高まります。ユーザー エクスペリエンスを向上させ、アップロードを確実に成功させるには、堅牢な再試行戦略を実装することが重要です。

戦略
  • 自動再試行: ユーザーにプロンプ​​トを表示する前に、失敗した部分を制限された回数だけ自動的に再試行します。
  • 再開可能なアップロード: アップロードを最初からやり直すのではなく、中断したところから再開できるように、アップロードされた部分を追跡します。
  • エラー処理: 再試行が失敗した場合に有益なエラー メッセージをユーザーに提供し、場合によってはネットワーク接続の確認などのアクションを提案します。

マルチパートアップロードのクリーンアップ

不完全なマルチパートアップロードは S3 バケットに蓄積され、ストレージスペースを消費し、コストが発生する可能性があります。

考慮事項
  • 未完了のアップロードを中止する: アップロードが失敗するかキャンセルされた場合は、アプリケーションが AbortMultipartUpload API を呼び出して、アップロードされた部分をクリーンアップしていることを確認してください。
  • ライフサイクル ルール: 一定期間 (例: 7 日) が経過すると、不完全なマルチパート アップロードを自動的に中止するように S3 ライフサイクル ポリシーを設定します。これにより、ストレージ コストを管理し、バケットをクリーンな状態に保つことができます。

ライフサイクル ルールの構成例:

// services/S3UploadService.js

import {
  S3Client,
  CreateMultipartUploadCommand,
  CompleteMultipartUploadCommand,
  UploadPartCommand,
  AbortMultipartUploadCommand,
  PutObjectCommand,
  GetObjectCommand,
  DeleteObjectCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

// Import credential providers
import {
  fromIni,
  fromInstanceMetadata,
  fromEnv,
  fromProcess,
} from '@aws-sdk/credential-providers';

export class S3UploadService {
  constructor() {
    this.s3BucketName = process.env.S3_BUCKET_NAME;
    this.s3Region = process.env.S3_REGION;

    this.s3Client = new S3Client({
      region: this.s3Region,
      credentials: this.getS3ClientCredentials(),
    });
  }

  // Method to generate AWS credentials securely
  getS3ClientCredentials() {
    if (process.env.NODE_ENV === 'development') {
      // In development, use credentials from environment variables
      return fromEnv();
    } else {
      // In production, use credentials from EC2 instance metadata or another secure method
      return fromInstanceMetadata();
    }
  }

  // Generate a presigned URL for single-part upload (PUT), download (GET), or deletion (DELETE)
  async generatePresignedUrl(key, operation) {
    let command;
    switch (operation) {
      case 'PUT':
        command = new PutObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      case 'GET':
        command = new GetObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      case 'DELETE':
        command = new DeleteObjectCommand({
          Bucket: this.s3BucketName,
          Key: key,
        });
        break;
      default:
        throw new Error(`Invalid operation "${operation}"`);
    }

    // Generate presigned URL
    return await getSignedUrl(this.s3Client, command, { expiresIn: 3600 }); // Expires in 1 hour
  }

  // Methods for multipart upload
  async createMultipartUpload(key) {
    const command = new CreateMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
    });
    const response = await this.s3Client.send(command);
    return response.UploadId;
  }

  async generateUploadPartUrl(key, uploadId, partNumber) {
    const command = new UploadPartCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
      PartNumber: partNumber,
    });

    return await getSignedUrl(this.s3Client, command, { expiresIn: 3600 });
  }

  async completeMultipartUpload(key, uploadId, parts) {
    const command = new CompleteMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
      MultipartUpload: { Parts: parts },
    });
    return await this.s3Client.send(command);
  }

  async abortMultipartUpload(key, uploadId) {
    const command = new AbortMultipartUploadCommand({
      Bucket: this.s3BucketName,
      Key: key,
      UploadId: uploadId,
    });
    return await this.s3Client.send(command);
  }
}

メインスレッド外でのマルチパートアップロードの処理

大きなファイルのアップロードはリソースを大量に消費する可能性があり、ブラウザのメイン スレッドが応答しなくなり、ユーザー エクスペリエンスが低下する可能性があります。

解決:
  • Web ワーカーを使用する: アップロード プロセスを Web ワーカーにオフロードします。 Web ワーカーは、Web アプリケーションのメイン実行スレッドとは別にバックグラウンドで実行されるため、UI をブロックすることなくリソースを大量に消費する操作を実行できます。
利点:
  • パフォーマンスの向上: メイン スレッドを解放し、アップロード プロセス中に UI の応答性を維持します。
  • メモリ使用量の削減: ワーカー内で大規模なデータ処理を処理できるため、メモリをより効果的に管理できます。
  • 安定性の強化: 大規模なアップロード中にブラウザが応答しなくなったりクラッシュしたりするリスクを軽減します。

7. ブラウザの互換性に関する考慮事項

クライアント側のマルチパート アップロードを実装する場合、ブラウザの互換性が確かに懸念されます。 *ファイル API、Blob スライス、Web ワーカー、ネットワーク リクエスト処理* など、大きなファイルのアップロードを処理するために必要な API や機能のサポート レベルはブラウザごとに異なります。 。これらの違いをうまく処理することは、サポートされているすべてのブラウザーで一貫性と信頼性の高いユーザー エクスペリエンスを確保するために非常に重要です。

互換性に関する懸念:

  • ファイル API と Blob メソッド: ほとんどの最新のブラウザーは Blob.slice() をサポートしていますが、古いブラウザーは Blob.webkitSlice() または Blob.mozSlice() を使用する場合があります。
  • Web Workers: 最新のブラウザではサポートされていますが、一部の古いブラウザではサポートされていないか、Internet Explorer には制限があります。
  • Fetch API と XMLHttpRequest: fetch() は広くサポートされていますが、fetch() によるアップロード進行状況イベントはすべてのブラウザーで一貫して利用できるわけではありません。
  • 最大同時接続数: サポートされているブラウザの最小公倍数に基づいて、同時アップロードの数を制限します (例: 6 つの同時接続)。
  • メモリ制約: ファイルを小さなチャンクに分割して処理し、ファイル全体を一度にメモリにロードしないようにします。
  • CORS: 必要な HTTP メソッド (PUT、POST など) とヘッダーをサポートするように S3 CORS ポリシーを設定します。

結論

署名付き URL とマルチパート アップロードを使用したクライアント側のアップロードを実装することで、任意のサイズのファイルの S3 への直接アップロードを効率的に処理でき、サーバーの負荷が軽減され、パフォーマンスが向上します。 AWS 認証情報を安全に管理し、署名付き URL の権限と有効期間を制限することで、セキュリティを最前線に保つことを忘れないでください。

このガイドでは、AWS S3、AWS SDK for JavaScript、および署名付き URL を使用して、安全でスケーラブルなファイル アップロード システムをセットアップするための段階的なアプローチを説明しました。提供されているコード例とベスト プラクティスを活用すれば、アプリケーションのファイル アップロード機能を強化することができます。

以上が大きなファイルのアップロードの最適化: AWS S3 への安全なクライアント側マルチパート アップロードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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