国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 web前端 js教程 優(yōu)化大文件上傳:安全地將客戶端分段上傳到 AWS S3

優(yōu)化大文件上傳:安全地將客戶端分段上傳到 AWS S3

Nov 08, 2024 am 07:22 AM

將大文件上傳到云端可能具有挑戰(zhàn)性 - 網(wǎng)絡(luò)中斷、瀏覽器限制和巨大的文件大小很容易破壞該過程。 Amazon S3(簡(jiǎn)單存儲(chǔ)服務(wù))是一種可擴(kuò)展、高速、基于 Web 的云存儲(chǔ)服務(wù),專為數(shù)據(jù)和應(yīng)用程序的在線備份和歸檔而設(shè)計(jì)。然而,將大文件上傳到 S3 需要小心處理,以確??煽啃院托阅?。

AWS S3 的分段上傳:這是一個(gè)功能強(qiáng)大的解決方案,可以將大文件分成更小的塊,通過獨(dú)立處理每個(gè)部分甚至并行上傳部分來實(shí)現(xiàn)更快、更可靠的上傳。這種方法不僅克服了文件大小限制(S3 需要對(duì)大于 5GB 的文件進(jìn)行分段上傳),而且還最大限度地降低了失敗的風(fēng)險(xiǎn),使其非常適合需要無縫、穩(wěn)健的文件上傳的應(yīng)用程序。

在本指南中,我們將詳細(xì)介紹客戶端分段上傳到 S3 的細(xì)節(jié),向您展示為什么它是處理大文件的明智選擇、如何安全地啟動(dòng)和運(yùn)行它以及需要注意哪些挑戰(zhàn)出去。我將提供分步說明、代碼示例和最佳實(shí)踐,以幫助您實(shí)現(xiàn)可靠的客戶端文件上傳解決方案。

準(zhǔn)備好升級(jí)您的文件上傳體驗(yàn)了嗎?讓我們開始吧!

服務(wù)器與客戶端上傳

設(shè)計(jì)文件上傳系統(tǒng)時(shí),您有兩個(gè)主要選擇:通過服務(wù)器上傳文件(服務(wù)器端)或直接從客戶端上傳文件到 S3(客戶端)。每種方法都有其優(yōu)點(diǎn)和缺點(diǎn)。

服務(wù)器端上傳

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

優(yōu)點(diǎn):

  • 增強(qiáng)的安全性:所有上傳均由服務(wù)器管理,確保 AWS 憑證的安全。

  • 更好的錯(cuò)誤處理:服務(wù)器可以更穩(wěn)健地管理重試、日志記錄和錯(cuò)誤處理。

  • 集中處理:文件可以在存儲(chǔ)到 S3 之前在服務(wù)器上進(jìn)行驗(yàn)證、處理或轉(zhuǎn)換。

缺點(diǎn):

  • 更高的服務(wù)器負(fù)載:大量上傳會(huì)消耗服務(wù)器資源(CPU、內(nèi)存、帶寬),這會(huì)影響性能并增加運(yùn)營(yíng)成本。

  • 潛在瓶頸:在高上傳流量期間,服務(wù)器可能成為單點(diǎn)故障或性能瓶頸,導(dǎo)致上傳緩慢或停機(jī)。

  • 成本增加:在服務(wù)器端處理上傳可能需要擴(kuò)展基礎(chǔ)設(shè)施以處理峰值負(fù)載,從而增加運(yùn)營(yíng)費(fèi)用。

客戶端上傳

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

優(yōu)點(diǎn):

  • 減少服務(wù)器負(fù)載:文件直接從用戶設(shè)備發(fā)送到 S3,釋放服務(wù)器資源。

  • 速度提高:由于繞過應(yīng)用程序服務(wù)器,用戶體驗(yàn)更快的上傳速度。

  • 成本效率:無需服務(wù)器基礎(chǔ)設(shè)施來處理大型上傳,從而可能降低成本。

  • 可擴(kuò)展性:非常適合在不給后端服務(wù)器造成壓力的情況下擴(kuò)展文件上傳。

缺點(diǎn):

  • 安全風(fēng)險(xiǎn):需要仔細(xì)處理 AWS 憑證和權(quán)限。必須安全地生成預(yù)簽名 URL,以防止未經(jīng)授權(quán)的訪問。

  • 有限控制:服務(wù)器端對(duì)上傳的監(jiān)督較少;錯(cuò)誤處理和重試通常在客戶端進(jìn)行管理。

  • 瀏覽器限制:瀏覽器有內(nèi)存和 API 限制,這可能會(huì)阻礙處理非常大的文件或影響低端設(shè)備上的性能。

實(shí)施安全客戶端上傳的分步指南

安全地實(shí)現(xiàn)客戶端上傳涉及前端應(yīng)用程序和安全后端服務(wù)之間的協(xié)調(diào)。后端服務(wù)的主要作用是生成預(yù)簽名 URL,允許客戶端將文件直接上傳到 S3,而無需暴露敏感的 AWS 憑證。

先決條件

  • AWS 賬戶:訪問有權(quán)使用 S3 的 AWS 賬戶。
  • AWS 開發(fā)工具包知識(shí):熟悉適用于 JavaScript 的 AWS 開發(fā)工具包 (v3) 或直接對(duì) AWS 服務(wù)進(jìn)行 API 調(diào)用。
  • 前端和后端開發(fā)技能:了解客戶端(JavaScript、React 等)和服務(wù)器端(Node.js、Express 等)編程。

1. 設(shè)置正確的架構(gòu)

要有效實(shí)現(xiàn)客戶端上傳,您需要:

  • 前端應(yīng)用程序:處理文件選擇、根據(jù)需要將文件拆分為多個(gè)部分,以及使用預(yù)簽名 URL 將各個(gè)部分上傳到 S3。
  • 后端服務(wù):一個(gè)安全服務(wù)器,提供用于生成預(yù)簽名 URL 以及初始化或完成分段上傳的 API。它可以保證您的 AWS 憑證的安全并強(qiáng)制執(zhí)行任何必要的業(yè)務(wù)邏輯或驗(yàn)證。

此架構(gòu)確保敏感操作在后端安全處理,而前端則管理上傳過程。

2. 后端創(chuàng)建上傳服務(wù)

為什么使用預(yù)簽名 URL?

預(yù)簽名 URL 允許客戶端直接與 S3 交互,執(zhí)行上傳文件等操作,而無需在客戶端提供 AWS 憑證。它們是安全的,因?yàn)椋?/p>

  • 它們是有時(shí)間限制的,并在指定期限后過期。
  • 它們可以被限制為特定操作(例如,PUT 用于上傳)。
  • 它們特定于特定的 S3 對(duì)象密鑰。

實(shí)施S3UploadService

在服務(wù)器上創(chuàng)建一個(gè)服務(wù)類,負(fù)責(zé):

a.定義 S3 存儲(chǔ)桶和區(qū)域
b.安全地建立 AWS 憑證。
c.提供生成預(yù)簽名 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 憑證得到安全管理。在生產(chǎn)中,建議使用附加到 EC2 實(shí)例或 ECS 任務(wù)的 IAM 角色,而不是硬編碼憑證或使用環(huán)境變量。

3. 實(shí)現(xiàn)后端 API 端點(diǎn)

在后端創(chuàng)建 API 端點(diǎn)來處理來自前端的請(qǐng)求。這些端點(diǎn)將利用 S3UploadService 來執(zhí)行操作。

// 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 應(yīng)用程序或您使用的任何框架中設(shè)置這些端點(diǎn)的路由。

4. 實(shí)現(xiàn)前端上傳器類

前端將處理選擇文件,根據(jù)文件大小決定是否執(zhí)行單部分或分段上傳,并管理上傳過程。

一般來說,AWS 建議“當(dāng)您的對(duì)象大小達(dá)到 100 MB 時(shí),您應(yīng)該考慮使用分段上傳,而不是在單個(gè)操作中上傳對(duì)象?!眮碓?br>

// 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. 安全注意事項(xiàng)和最佳實(shí)踐

  • 限制預(yù)簽名 URL 權(quán)限:確保預(yù)簽名 URL 僅授予必要的權(quán)限(例如,僅允許上傳的 PUT 操作)。
  • 設(shè)置適當(dāng)?shù)倪^期時(shí)間:預(yù)簽名 URL 應(yīng)在合理的時(shí)間(例如 15 分鐘到 1 小時(shí))后過期,以最大限度地減少誤用的時(shí)間。
  • 驗(yàn)證文件元數(shù)據(jù):在后端,驗(yàn)證從客戶端發(fā)送的任何元數(shù)據(jù)或參數(shù)以防止操縱(例如,強(qiáng)制執(zhí)行允許的文件類型或大?。?。
  • 使用 HTTPS:始終使用 HTTPS 進(jìn)行客戶端和后端之間的通信,以及訪問 S3 時(shí),以保護(hù)傳輸中的數(shù)據(jù)。
  • 監(jiān)控和日志:在后端和 S3 上實(shí)施日志記錄和監(jiān)控,以檢測(cè)任何異常活動(dòng)或錯(cuò)誤。

6. 其他注意事項(xiàng)

限制對(duì)象大小

雖然 AWS S3 支持大小高達(dá) 5 TiB(太字節(jié))的對(duì)象,但由于瀏覽器限制和客戶端資源限制,直接從瀏覽器上傳如此大的文件是不切實(shí)際的,而且通常是不可能的。處理非常大的文件時(shí),瀏覽器可能會(huì)崩潰或變得無響應(yīng),特別是需要在內(nèi)存中處理它們時(shí)。

推薦:
  • 設(shè)置實(shí)際限制:定義您的應(yīng)用程序支持客戶端上傳的最大文件大?。ɡ?,100 GB 或更少)。
  • 通知用戶:向用戶提供有關(guān)允許的最大文件大小的反饋,并在開始上傳之前在客戶端處理驗(yàn)證。

重試策略

上傳大文件會(huì)增加上傳過程中網(wǎng)絡(luò)中斷或失敗的風(fēng)險(xiǎn)。實(shí)施穩(wěn)健的重試策略對(duì)于增強(qiáng)用戶體驗(yàn)并確保成功上傳至關(guān)重要。

策略
  • 自動(dòng)重試:在提示用戶之前自動(dòng)重試失敗的部分有限次數(shù)。
  • 可恢復(fù)上傳:跟蹤上傳的部分,以便上傳可以從中斷處恢復(fù),而不是重新開始。
  • 錯(cuò)誤處理:如果重試失敗,向用戶提供信息豐富的錯(cuò)誤消息,可能會(huì)建議檢查網(wǎng)絡(luò)連接等操作。

分段上傳清理

不完整的分段上傳可能會(huì)累積在您的 S3 存儲(chǔ)桶中,消耗存儲(chǔ)空間并可能產(chǎn)生費(fèi)用。

注意事項(xiàng)
  • 中止未完成的上傳:如果上傳失敗或被取消,請(qǐng)確保您的應(yīng)用程序調(diào)用 AbortMultipartUpload API 來清理所有已上傳的部分。
  • 生命周期規(guī)則:配置 S3 生命周期策略以在一段時(shí)間(例如 7 天)后自動(dòng)中止不完整的分段上傳。這有助于管理存儲(chǔ)成本并保持水桶清潔。

生命周期規(guī)則配置示例:

// 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);
  }
}

從主線程處理分段上傳

上傳大文件可能會(huì)占用大量資源,并可能導(dǎo)致瀏覽器主線程無響應(yīng),從而導(dǎo)致用戶體驗(yàn)不佳。

解決方案:
  • 使用 Web Workers:將上傳過程卸載到 Web Worker。 Web Workers 在后臺(tái)運(yùn)行,與 Web 應(yīng)用程序的主執(zhí)行線程分開,允許您執(zhí)行資源密集型操作而不阻塞 UI。
好處:
  • 提高性能:釋放主線程,確保 UI 在上傳過程中保持響應(yīng)。
  • 減少內(nèi)存使用:幫助更有效地管理內(nèi)存,因?yàn)榭梢栽诠ぷ骶€程內(nèi)處理大數(shù)據(jù)處理。
  • 增強(qiáng)穩(wěn)定性:降低瀏覽器在大量上傳期間無響應(yīng)或崩潰的風(fēng)險(xiǎn)。

7. 瀏覽器兼容性注意事項(xiàng)

在實(shí)現(xiàn)客戶端分段上傳時(shí),瀏覽器兼容性確實(shí)是一個(gè)問題。不同的瀏覽器可能對(duì)處理大文件上傳所需的 API 和功能有不同級(jí)別的支持,例如 *文件 API、Blob 切片、Web Workers 和網(wǎng)絡(luò)請(qǐng)求處理* 。成功應(yīng)對(duì)這些差異對(duì)于確保在所有受支持的瀏覽器上獲得一致且可靠的用戶體驗(yàn)至關(guān)重要。

兼容性問題:

  • 文件 API 和 Blob 方法:大多數(shù)現(xiàn)代瀏覽器支持 Blob.slice(),但較舊的瀏覽器可能使用 Blob.webkitSlice() 或 Blob.mozSlice()。
  • Web Workers:在現(xiàn)代瀏覽器中受支持,但在某些較舊的瀏覽器中不受支持,或者在 Internet Explorer 中受到限制。
  • Fetch API 和 XMLHttpRequest:雖然 fetch() 得到廣泛支持,但使用 fetch() 的上傳進(jìn)度事件并非在所有瀏覽器上一致可用。
  • 最大并發(fā)連接數(shù):根據(jù)支持的瀏覽器之間的最低公分母限制同時(shí)上傳的數(shù)量(例如 6 個(gè)并發(fā)連接)。
  • 內(nèi)存限制:以小塊的形式處理文件,并避免一次將整個(gè)文件加載到內(nèi)存中。
  • CORS:配置 S3 CORS 策略以支持必要的 HTTP 方法(例如,PUT、POST)和標(biāo)頭。

結(jié)論

通過使用預(yù)簽名 URL 和分段上傳實(shí)現(xiàn)客戶端上傳,您可以高效地直接處理任意大小的文件上傳到 S3,從而減少服務(wù)器負(fù)載并提高性能。請(qǐng)記住,通過安全地管理 AWS 憑證并限制預(yù)簽名 URL 的權(quán)限和生命周期,將安全性放在首位。

本指南提供了使用 AWS S3、AWS SDK for JavaScript 和預(yù)簽名 URL 設(shè)置安全且可擴(kuò)展的文件上傳系統(tǒng)的分步方法。通過提供的代碼示例和最佳實(shí)踐,您就可以很好地增強(qiáng)應(yīng)用程序的文件上傳功能。

以上是優(yōu)化大文件上傳:安全地將客戶端分段上傳到 AWS S3的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本站聲明
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機(jī)

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)代碼編輯軟件(SublimeText3)

Java vs. JavaScript:清除混亂 Java vs. JavaScript:清除混亂 Jun 20, 2025 am 12:27 AM

Java和JavaScript是不同的編程語言,各自適用于不同的應(yīng)用場(chǎng)景。Java用于大型企業(yè)和移動(dòng)應(yīng)用開發(fā),而JavaScript主要用于網(wǎng)頁開發(fā)。

JavaScript評(píng)論:簡(jiǎn)短說明 JavaScript評(píng)論:簡(jiǎn)短說明 Jun 19, 2025 am 12:40 AM

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

如何在JS中與日期和時(shí)間合作? 如何在JS中與日期和時(shí)間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時(shí)間處理需注意以下幾點(diǎn):1.創(chuàng)建Date對(duì)象有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設(shè)置時(shí)間信息可用get和set方法,注意月份從0開始;3.手動(dòng)格式化日期需拼接字符串,也可使用第三方庫;4.處理時(shí)區(qū)問題建議使用支持時(shí)區(qū)的庫,如Luxon。掌握這些要點(diǎn)能有效避免常見錯(cuò)誤。

為什么要將標(biāo)簽放在的底部? 為什么要將標(biāo)簽放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

JavaScript與Java:開發(fā)人員的全面比較 JavaScript與Java:開發(fā)人員的全面比較 Jun 20, 2025 am 12:21 AM

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)

JavaScript:探索用于高效編碼的數(shù)據(jù)類型 JavaScript:探索用于高效編碼的數(shù)據(jù)類型 Jun 20, 2025 am 12:46 AM

javascripthassevenfundaMentalDatatypes:數(shù)字,弦,布爾值,未定義,null,object和symbol.1)numberSeadUble-eaduble-ecisionFormat,forwidevaluerangesbutbecautious.2)

什么是在DOM中冒泡和捕獲的事件? 什么是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個(gè)階段,捕獲是從頂層向下到目標(biāo)元素,冒泡是從目標(biāo)元素向上傳播到頂層。1.事件捕獲通過addEventListener的useCapture參數(shù)設(shè)為true實(shí)現(xiàn);2.事件冒泡是默認(rèn)行為,useCapture設(shè)為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委托,提高動(dòng)態(tài)內(nèi)容處理效率;5.捕獲可用于提前攔截事件,如日志記錄或錯(cuò)誤處理。了解這兩個(gè)階段有助于精確控制JavaScript響應(yīng)用戶操作的時(shí)機(jī)和方式。

See all articles