Heim  >  Artikel  >  Web-Frontend  >  Optimierung großer Datei-Uploads: Sichere clientseitige mehrteilige Uploads auf AWS S3

Optimierung großer Datei-Uploads: Sichere clientseitige mehrteilige Uploads auf AWS S3

Susan Sarandon
Susan SarandonOriginal
2024-11-08 07:22:02441Durchsuche

Das Hochladen großer Dateien in die Cloud kann eine Herausforderung sein – Netzwerkunterbrechungen, Browsereinschränkungen und große Dateigrößen können den Prozess leicht stören. Amazon S3 (Simple Storage Service) ist ein skalierbarer, webbasierter Hochgeschwindigkeits-Cloud-Speicherdienst, der für die Online-Sicherung und Archivierung von Daten und Anwendungen entwickelt wurde. Das Hochladen großer Dateien auf S3 erfordert jedoch eine sorgfältige Handhabung, um Zuverlässigkeit und Leistung sicherzustellen.

Nutzen Sie den mehrteiligen Upload von AWS S3: eine leistungsstarke Lösung, die große Dateien in kleinere Teile aufteilt und so schnellere und zuverlässigere Uploads ermöglicht, indem sie jeden Teil unabhängig angeht und Teile sogar parallel hochlädt. Diese Methode überwindet nicht nur Dateigrößenbeschränkungen (S3 erfordert einen mehrteiligen Upload für Dateien, die größer als 5 GB sind), sondern minimiert auch das Fehlerrisiko und eignet sich daher perfekt für Anwendungen, die nahtlose, robuste Datei-Uploads benötigen.

In diesem Leitfaden erläutern wir die Besonderheiten clientseitiger Multipart-Uploads auf S3 und zeigen Ihnen, warum es die kluge Wahl für den Umgang mit großen Dateien ist, wie Sie es sicher zum Laufen bringen und welche Herausforderungen Sie im Auge behalten müssen raus für. Ich stelle Schritt-für-Schritt-Anleitungen, Codebeispiele und Best Practices zur Verfügung, um Sie bei der Implementierung einer zuverlässigen clientseitigen Datei-Upload-Lösung zu unterstützen.

Sind Sie bereit, Ihr Datei-Upload-Erlebnis zu verbessern? Lasst uns eintauchen!

Server- vs. clientseitige Uploads

Beim Entwerfen eines Datei-Upload-Systems haben Sie zwei Hauptoptionen: Hochladen von Dateien über Ihren Server (serverseitig) oder Hochladen von Dateien direkt vom Client auf S3 (clientseitig). Jeder Ansatz hat seine Vor- und Nachteile.

Serverseitige Uploads

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

Vorteile:

  • Erhöhte Sicherheit: Alle Uploads werden vom Server verwaltet, sodass die AWS-Anmeldeinformationen sicher bleiben.

  • Bessere Fehlerbehandlung: Server können Wiederholungsversuche, Protokollierung und Fehlerbehandlung robuster verwalten.

  • Zentralisierte Verarbeitung: Dateien können auf dem Server validiert, verarbeitet oder konvertiert werden, bevor sie in S3 gespeichert werden.

Nachteile:

  • Höhere Serverlast: Große Uploads verbrauchen Serverressourcen (CPU, Speicher, Bandbreite), was sich auf die Leistung auswirken und die Betriebskosten erhöhen kann.

  • Potenzielle Engpässe: Der Server kann bei hohem Upload-Verkehr zu einem Single Point of Failure oder einem Leistungsengpass werden, was zu langsamen Uploads oder Ausfallzeiten führt.

  • Erhöhte Kosten: Die serverseitige Bearbeitung von Uploads erfordert möglicherweise eine Skalierung Ihrer Infrastruktur, um Spitzenlasten zu bewältigen, was zu höheren Betriebskosten führt.

Clientseitige Uploads

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

Vorteile:

  • Reduzierte Serverlast: Dateien werden direkt vom Gerät des Benutzers an S3 gesendet, wodurch Serverressourcen freigegeben werden.

  • Verbesserte Geschwindigkeit: Benutzer erleben schnellere Uploads, da sie den Anwendungsserver umgehen.

  • Kosteneffizienz: Macht eine Serverinfrastruktur zur Verarbeitung großer Uploads überflüssig und senkt möglicherweise die Kosten.

  • Skalierbarkeit: Ideal zum Skalieren von Datei-Uploads, ohne Backend-Server zu belasten.

Nachteile:

  • Sicherheitsrisiken: Erfordert einen sorgfältigen Umgang mit AWS-Anmeldeinformationen und -Berechtigungen. Vorsignierte URLs müssen sicher generiert werden, um unbefugten Zugriff zu verhindern.

  • Eingeschränkte Kontrolle: Weniger serverseitige Kontrolle über Uploads; Fehlerbehandlung und Wiederholungsversuche werden oft auf dem Client verwaltet.

  • Browsereinschränkungen: Browser haben Speicher- und API-Einschränkungen, die die Verarbeitung sehr großer Dateien behindern oder die Leistung auf Geräten der unteren Preisklasse beeinträchtigen können.

Schritt-für-Schritt-Anleitung zur Implementierung sicherer clientseitiger Uploads

Die sichere Implementierung clientseitiger Uploads erfordert die Koordination zwischen Ihrer Frontend-Anwendung und einem sicheren Backend-Dienst. Die Hauptaufgabe des Backend-Dienstes besteht darin, vorsignierte URLs zu generieren, die es dem Client ermöglichen, Dateien direkt auf S3 hochzuladen, ohne vertrauliche AWS-Anmeldeinformationen preiszugeben.

Voraussetzungen

  • AWS-Konto: Zugriff auf ein AWS-Konto mit Berechtigungen zur Verwendung von S3.
  • AWS SDK-Kenntnisse: Vertrautheit mit dem AWS SDK für JavaScript (v3) oder dem Durchführen direkter API-Aufrufe an AWS-Dienste.
  • Frontend- und Backend-Entwicklungsfähigkeiten: Verständnis sowohl der clientseitigen (JavaScript, React usw.) als auch der serverseitigen (Node.js, Express usw.) Programmierung.

1. Einrichten der richtigen Architektur

Um clientseitige Uploads effektiv zu implementieren, benötigen Sie:

  • Frontend-Anwendung: Verwaltet die Dateiauswahl, teilt Dateien bei Bedarf in Teile auf und lädt Teile mithilfe vorsignierter URLs in S3 hoch.
  • Backend-Dienst: Ein sicherer Server, der APIs zum Generieren vorsignierter URLs und zum Initialisieren oder Abschließen mehrteiliger Uploads bereitstellt. Es schützt Ihre AWS-Anmeldeinformationen und erzwingt alle erforderlichen Geschäftslogiken oder Validierungen.

Diese Architektur stellt sicher, dass sensible Vorgänge sicher im Backend abgewickelt werden, während das Frontend den Upload-Prozess verwaltet.

2. Erstellen des Upload-Dienstes im Backend

Warum vorsignierte URLs verwenden?

Vordefinierte URLs ermöglichen es Clients, direkt mit S3 zu interagieren und Vorgänge wie das Hochladen von Dateien auszuführen, ohne dass AWS-Anmeldeinformationen auf der Clientseite erforderlich sind. Sie sind sicher, weil:

  • Sie sind zeitlich begrenzt und verfallen nach einer bestimmten Dauer.
  • Sie können auf bestimmte Vorgänge beschränkt werden (z. B. PUT zum Hochladen).
  • Sie sind spezifisch für einen bestimmten S3-Objektschlüssel.

Implementierung des S3UploadService

Erstellen Sie auf Ihrem Server eine Serviceklasse, die verantwortlich ist für:

a. Definieren des S3-Buckets und der Region
B. AWS-Anmeldeinformationen sicher einrichten.
C. Bereitstellung von Methoden zum Generieren vorsignierter URLs und zum Verwalten mehrteiliger Uploads.

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

Hinweis: Stellen Sie sicher, dass Ihre AWS-Anmeldeinformationen sicher verwaltet werden. In der Produktion wird empfohlen, IAM-Rollen zu verwenden, die Ihren EC2-Instanzen oder ECS-Aufgaben zugeordnet sind, anstatt Anmeldeinformationen fest zu codieren oder Umgebungsvariablen zu verwenden.

3. Implementierung der Backend-API-Endpunkte

Erstellen Sie API-Endpunkte in Ihrem Backend, um Anfragen vom Frontend zu verarbeiten. Diese Endpunkte nutzen den S3UploadService, um Aktionen auszuführen.

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

Richten Sie die Routen für diese Endpunkte in Ihrer Express-App oder dem von Ihnen verwendeten Framework ein.

4. Implementierung der Frontend-Uploader-Klasse

Das Frontend übernimmt die Auswahl der Dateien, entscheidet anhand der Dateigröße, ob ein einteiliger oder mehrteiliger Upload durchgeführt werden soll, und verwaltet den Upload-Prozess.

Im Allgemeinen empfiehlt AWS: „Wenn Ihre Objektgröße 100 MB erreicht, sollten Sie mehrteilige Uploads in Betracht ziehen, anstatt das Objekt in einem einzigen Vorgang hochzuladen.“ Quelle

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

Anwendungsbeispiel

// 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. Sicherheitsüberlegungen und Best Practices

  • Vorsignierte URL-Berechtigungen einschränken: Stellen Sie sicher, dass vorsignierte URLs nur die erforderlichen Berechtigungen gewähren (z. B. nur PUT-Vorgänge für Uploads zulassen).
  • Geeignete Ablaufzeiten festlegen: Vorsignierte URLs sollten nach einer angemessenen Zeit (z. B. 15 Minuten bis 1 Stunde) ablaufen, um das Zeitfenster für Missbrauch zu minimieren.
  • Dateimetadaten validieren: Validieren Sie im Backend alle vom Client gesendeten Metadaten oder Parameter, um Manipulationen zu verhindern (z. B. Erzwingen zulässiger Dateitypen oder -größen).
  • HTTPS verwenden: Verwenden Sie immer HTTPS für die Kommunikation zwischen dem Client und Ihrem Backend und beim Zugriff auf S3, um Daten während der Übertragung zu schützen.
  • Überwachen und protokollieren: Implementieren Sie Protokollierung und Überwachung sowohl im Backend als auch in S3, um ungewöhnliche Aktivitäten oder Fehler zu erkennen.

6. Zusätzliche Überlegungen

Begrenzung der Objektgröße

Während AWS S3 Objekte mit einer Größe von bis zu 5 TiB (Terabyte) unterstützt, ist das Hochladen solch großer Dateien direkt aus einem Browser aufgrund von Browserbeschränkungen und clientseitigen Ressourcenbeschränkungen unpraktisch und oft unmöglich. Browser können abstürzen oder nicht mehr reagieren, wenn sie extrem große Dateien verarbeiten, insbesondere wenn sie im Speicher verarbeitet werden müssen.

Empfehlung:
  • Praktische Grenzen festlegen: Definieren Sie eine maximale Dateigröße, die Ihre Anwendung für clientseitige Uploads unterstützt (z. B. 100 GB oder weniger).
  • Benutzer informieren: Geben Sie den Benutzern Feedback zur maximal zulässigen Dateigröße und führen Sie die Validierung auf der Clientseite durch, bevor Sie den Upload starten.

Wiederholungsstrategie

Das Hochladen großer Dateien erhöht das Risiko von Netzwerkunterbrechungen oder Ausfällen während des Upload-Vorgangs. Die Implementierung einer robusten Wiederholungsstrategie ist entscheidend, um das Benutzererlebnis zu verbessern und erfolgreiche Uploads sicherzustellen.

Strategien
  • Automatische Wiederholungsversuche: Fehlgeschlagene Teile automatisch eine begrenzte Anzahl von Malen wiederholen, bevor der Benutzer dazu aufgefordert wird.
  • Fortsetzbare Uploads: Behalten Sie den Überblick über hochgeladene Teile, damit der Upload dort fortgesetzt werden kann, wo er aufgehört hat, anstatt von vorne zu beginnen.
  • Fehlerbehandlung: Stellen Sie dem Benutzer informative Fehlermeldungen zur Verfügung, wenn Wiederholungsversuche fehlschlagen, und schlagen Sie möglicherweise Aktionen wie die Überprüfung seiner Netzwerkverbindung vor.

Mehrteilige Upload-Bereinigung

Unvollständige mehrteilige Uploads können sich in Ihrem S3-Bucket ansammeln, Speicherplatz verbrauchen und möglicherweise Kosten verursachen.

Überlegungen
  • Unvollendete Uploads abbrechen: Wenn ein Upload fehlschlägt oder abgebrochen wird, stellen Sie sicher, dass Ihre Anwendung die AbortMultipartUpload-API aufruft, um alle hochgeladenen Teile zu bereinigen.
  • Lebenszyklusregeln: Konfigurieren Sie S3-Lebenszyklusrichtlinien, um unvollständige mehrteilige Uploads nach einem bestimmten Zeitraum (z. B. 7 Tage) automatisch abzubrechen. Dies hilft bei der Verwaltung der Lagerkosten und hält Ihren Eimer sauber.

Beispiel für die Konfiguration einer Lebenszyklusregel:

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

Umgang mit mehrteiligen Uploads außerhalb des Hauptthreads

Das Hochladen großer Dateien kann ressourcenintensiv sein und dazu führen, dass der Hauptthread des Browsers nicht mehr reagiert, was zu einer schlechten Benutzererfahrung führt.

Lösung:
  • Web Worker verwenden: Verlagern Sie den Upload-Prozess auf einen Web Worker. Web Worker werden im Hintergrund ausgeführt, getrennt vom Hauptausführungsthread der Webanwendung, sodass Sie ressourcenintensive Vorgänge ausführen können, ohne die Benutzeroberfläche zu blockieren.
Vorteile:
  • Verbesserte Leistung: Macht den Hauptthread frei und stellt sicher, dass die Benutzeroberfläche während des Upload-Vorgangs reaktionsfähig bleibt.
  • Reduzierte Speichernutzung: Hilft bei der effektiveren Speicherverwaltung, da die Verarbeitung großer Datenmengen innerhalb des Workers abgewickelt werden kann.
  • Verbesserte Stabilität: Reduziert das Risiko, dass der Browser bei großen Uploads nicht mehr reagiert oder abstürzt.

7. Überlegungen zur Browserkompatibilität

Bei der Implementierung clientseitiger mehrteiliger Uploads ist die Browserkompatibilität tatsächlich ein Problem. Verschiedene Browser verfügen möglicherweise über unterschiedliche Unterstützungsstufen für die APIs und Funktionen, die für die Verarbeitung großer Datei-Uploads erforderlich sind, wie z. B. die *Datei-API, Blob-Slicing, Web Worker und Netzwerkanfrageverarbeitung* . Die erfolgreiche Bewältigung dieser Unterschiede ist entscheidend, um eine konsistente und zuverlässige Benutzererfahrung in allen unterstützten Browsern sicherzustellen.

Kompatibilitätsbedenken:

  • Datei-API und Blob-Methoden: Die meisten modernen Browser unterstützen Blob.slice(), ältere Browser verwenden jedoch möglicherweise Blob.webkitSlice() oder Blob.mozSlice().
  • Web Worker: Wird in modernen Browsern unterstützt, jedoch nicht in einigen älteren oder mit Einschränkungen im Internet Explorer.
  • Abruf-API und XMLHttpRequest: Obwohl fetch() weithin unterstützt wird, sind Upload-Fortschrittsereignisse mit fetch() nicht in allen Browsern konsistent verfügbar.
  • Maximale gleichzeitige Verbindungen: Begrenzen Sie die Anzahl gleichzeitiger Uploads basierend auf dem kleinsten gemeinsamen Nenner Ihrer unterstützten Browser (z. B. 6 gleichzeitige Verbindungen).
  • Speicherbeschränkungen: Verarbeiten Sie Dateien in kleinen Blöcken und vermeiden Sie, die gesamte Datei auf einmal in den Speicher zu laden.
  • CORS: Konfigurieren Sie S3 CORS-Richtlinien zur Unterstützung der erforderlichen HTTP-Methoden (z. B. PUT, POST) und Header.

Abschluss

Durch die Implementierung clientseitiger Uploads mit vorsignierten URLs und mehrteiligem Upload können Sie Datei-Uploads jeder Größe direkt in S3 effizient verarbeiten, wodurch die Serverlast reduziert und die Leistung verbessert wird. Denken Sie daran, die Sicherheit im Vordergrund zu halten, indem Sie AWS-Anmeldeinformationen sicher verwalten und die Berechtigungen und die Lebensdauer vorsignierter URLs begrenzen.

Diese Anleitung bietet einen schrittweisen Ansatz zum Einrichten eines sicheren und skalierbaren Datei-Upload-Systems mit AWS S3, dem AWS SDK für JavaScript und vorsignierten URLs. Mit den bereitgestellten Codebeispielen und Best Practices sind Sie auf dem besten Weg, die Datei-Upload-Funktionen Ihrer Anwendung zu verbessern.

Das obige ist der detaillierte Inhalt vonOptimierung großer Datei-Uploads: Sichere clientseitige mehrteilige Uploads auf AWS S3. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn