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

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

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

Nov 08, 2024 am 07:22 AM

將大檔案上傳到雲(yún)端可能具有挑戰(zhàn)性 - 網(wǎng)路中斷、瀏覽器限制和龐大的檔案大小很容易破壞這個(gè)過(guò)程。 Amazon S3(簡(jiǎn)單儲(chǔ)存服務(wù))是一種可擴(kuò)展、高速、基於 Web 的雲(yún)端儲(chǔ)存服務(wù),專為資料和應(yīng)用程式的線上備份和歸檔而設(shè)計(jì)。然而,將大檔案上傳到 S3 需要小心處理,以確??煽啃院托?。

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

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

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

伺服器與客戶端上傳

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

伺服器端上傳

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

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

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

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

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

缺點(diǎn):

  • 更高的伺服器負(fù)載:大量上傳會(huì)消耗伺服器資源(CPU、記憶體、頻寬),這會(huì)影響效能並增加營(yíng)運(yùn)成本。

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

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

客戶端上傳

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

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

  • 減少伺服器負(fù)載:檔案直接從使用者裝置傳送到 S3,釋放伺服器資源。

  • 速度提高:由於繞過(guò)應(yīng)用程式伺服器,使用者體驗(yàn)更快的上傳速度。

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

  • 可擴(kuò)充性:非常適合在不給後端伺服器造成壓力的情況下擴(kuò)展檔案上傳。

缺點(diǎn):

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

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

  • 瀏覽器限制:瀏覽器有記憶體和 API 限制,這可能會(huì)阻礙處理非常大的檔案或影響低階裝置上的效能。

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

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

先決條件

  • AWS 帳戶:存取有權(quán)使用 S3 的 AWS 帳戶。
  • AWS 開(kāi)發(fā)工具包知識(shí):熟悉適用於 JavaScript 的 AWS 開(kāi)發(fā)工具包 (v3) 或直接對(duì) AWS 服務(wù)進(jìn)行 API 呼叫。
  • 前端和後端開(kāi)發(fā)技能:了解客戶端(JavaScript、React 等)和伺服器端(Node.js、Express 等)程式設(shè)計(jì)。

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

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

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

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

2. 後端建立上傳服務(wù)

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

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

  • 它們是有時(shí)間限制的,並在指定期限後過(guò)期。
  • 它們可以被限制為特定操作(例如,PUT 用於上傳)。
  • 它們特定於特定的 S3 物件金鑰。

實(shí)作S3UploadService

在伺服器上建立一個(gè)服務(wù)類,負(fù)責(zé):

a.定義 S3 儲(chǔ)存桶和區(qū)域
b.安全地建立 AWS 憑證。
c.提供產(chǎn)生預(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 執(zhí)行個(gè)體或 ECS 任務(wù)的 IAM 角色,而不是硬編碼憑證或使用環(huán)境變數(shù)。

3. 實(shí)作後端 API 端點(diǎn)

在後端建立 API 端點(diǎn)來(lái)處理來(lái)自前端的請(qǐng)求。這些端點(diǎn)將會(huì)利用 S3UploadService 來(lái)執(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í)作前端上傳器類

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

一般來(lái)說(shuō),AWS 建議「當(dāng)您的物件大小達(dá)到 100 MB 時(shí),您應(yīng)該考慮使用分段上傳,而不是在單一操作中上傳物件?!箒?lái)源

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

使用範(fàn)例

// 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ù)倪^(guò)期時(shí)間:預(yù)簽 URL 應(yīng)在合理的時(shí)間(例如 15 分鐘到 1 小時(shí))後過(guò)期,以最大限度地減少誤用的時(shí)間。
  • 驗(yàn)證檔案元資料:在後端,驗(yàn)證從客戶端發(fā)送的任何元資料或參數(shù)以防止操縱(例如,強(qiáng)制執(zhí)行允許的檔案類型或大?。?。
  • 使用 HTTPS:請(qǐng)務(wù)必使用 HTTPS 進(jìn)行客戶端和後端之間的通信,以及存取 S3 時(shí),以保護(hù)傳輸中的資料。
  • 監(jiān)控和日誌:在後端和 S3 上實(shí)作日誌記錄和監(jiān)控,以偵測(cè)任何異常活動(dòng)或錯(cuò)誤。

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

限制物件大小

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

推薦:
  • 設(shè)定實(shí)際限制:定義您的應(yīng)用程式支援用戶端上傳的最大檔案大?。ɡ?,100 GB 或更少)。
  • 通知使用者:向使用者提供有關(guān)允許的最大檔案大小的回饋,並在開(kāi)始上傳之前在客戶端處理驗(yàn)證。

重試策略

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

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

分段上傳清理

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

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

生命週期規(guī)則配置範(fàn)例:

// 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ì)佔(zhàn)用大量資源,並可能導(dǎo)致瀏覽器主執(zhí)行緒無(wú)回應(yīng),從而導(dǎo)致使用者體驗(yàn)不佳。

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

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

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

相容性問(wè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ā)連線)。
  • 記憶體限制:以小塊的形式處理文件,並避免一次將整個(gè)文件載入記憶體。
  • CORS:設(shè)定 S3 CORS 策略以支援必要的 HTTP 方法(例如,PUT、POST)和標(biāo)頭。

結(jié)論

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

本指南提供了使用 AWS S3、AWS SDK for JavaScript 和預(yù)簽名 URL 設(shè)定安全且可擴(kuò)充的檔案上傳系統(tǒng)的逐步方法。透過(guò)提供的程式碼範(fàn)例和最佳實(shí)踐,您就可以很好地增強(qiáng)應(yīng)用程式的檔案上傳功能。

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

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)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脫衣器

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整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

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

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

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

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

掌握J(rèn)avaScript評(píng)論:綜合指南 掌握J(rèn)avaScript評(píng)論:綜合指南 Jun 14, 2025 am 12:11 AM

評(píng)論arecrucialinjavascriptformaintainingclarityclarityandfosteringCollaboration.1)heelpindebugging,登機(jī),andOnderStandingCodeeVolution.2)使用林格forquickexexplanations andmentmentsmmentsmmentsmments andmmentsfordeffordEffordEffordEffordEffordEffordEffordEffordEddeScriptions.3)bestcractices.3)bestcracticesincracticesinclud

如何在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開(kāi)始;3.手動(dòng)格式化日期需拼接字符串,也可使用第三方庫(kù);4.處理時(shí)區(qū)問(wèn)題建議使用支持時(shí)區(qū)的庫(kù),如Luxon。掌握這些要點(diǎn)能有效避免常見(jiàn)錯(cuò)誤。

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

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

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

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

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

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

Java和JavaScript有什麼區(qū)別? Java和JavaScript有什麼區(qū)別? Jun 17, 2025 am 09:17 AM

Java和JavaScript是不同的編程語(yǔ)言。 1.Java是靜態(tài)類型、編譯型語(yǔ)言,適用於企業(yè)應(yīng)用和大型系統(tǒng)。 2.JavaScript是動(dòng)態(tài)類型、解釋型語(yǔ)言,主要用於網(wǎng)頁(yè)交互和前端開(kāi)發(fā)。

See all articles