So verarbeiten Sie Datei-Uploads mit Fastify in Node.js
Amarachi Aso
8. Dezember 2022
0 Min. LesezeitDatei-Uploads gehören zu den häufig benötigten Funktionen in Webanwendungen. Deshalb bieten viele Web-Frameworks Möglichkeiten, mit denen serverseitige Anwendungen Dateien annehmen und verarbeiten können. Das gilt auch für Fastify, ein Node.js-Web-Framework, das oft als Nachfolger von Express angesehen wird. Es ist schnell und legt großen Wert auf eine optimale Developer Experience, eine leistungsstarke Plugin-Architektur und möglichst wenig Overhead.
In diesem Tutorial richten Sie Datei-Uploads mit dem Fastify-Framework in einer Node.js-Anwendung ein. Sie erfahren, wie Datei-Uploads auf einem typischen Server funktionieren und wie Sie sie in einer Fastify-Serveranwendung verarbeiten.
Grundlagen des Datei-Uploads
Wenn Sie Dateien auf einen Anwendungsserver hochladen möchten, muss ein Client-Computer eine POST-Anfrage an den Server senden. Im Anfragerumpf werden Daten übermittelt, wie sie typischerweise über HTML-Formulare gesendet werden. HTML-Formulare bieten drei Methoden zur Datenkodierung:
application/x-www-form-urlencoded(Standard) ist der standardmäßige Content-Type bzw. die standardmäßige Kodierung für HTML-Formulare. Wenn jedoch Dateien über dieses Formular übermittelt werden, müssen sie mit der Methodemultipart/form-datakodiert werden.multipart/form-datadient dazu, die mehreren Teile bzw. Felder eines HTML-Formulars darzustellen. Diese Teile werden als Name-Wert-Paare im Anfragerumpf übermittelt. Die Name-Wert-Paare entsprechen jeweils dem Namen und Wert der Eingabefelder.text/plainwird zum Senden unformatierten Klartexts verwendet und kann nicht zum Senden von Dateien genutzt werden.
Wenn Dateien an einen Anwendungsserver gesendet werden, soll der Server sie in der Regel verarbeiten, speichern oder beides tun. Serveranwendungen können hochgeladene Dateien auf verschiedene Weise verarbeiten und speichern, zum Beispiel:
Sie im Dateisystem des eigenen Servers speichern. Das kann in einem dedizierten Verzeichnis auf demselben Server geschehen, auf dem Ihre Anwendung läuft, oder auf einem anderen Server, der ausschließlich zum Speichern von Dateien vorgesehen ist.
Sie in einer Datenbank speichern.
Die Dateien in einen Cloud-Speicher wie Amazon S3 oder Cloudinary hochladen.
In diesem Tutorial geht es um die erste Methode zur Verarbeitung von Datei-Uploads.
Datei-Uploads mit Fastify implementieren
Für dieses Tutorial benötigen Sie Folgendes:
Node.js ist installiert
Einen Code-Editor Ihrer Wahl, zum Beispiel Visual Studio Code (VS Code)
Postman: Sie können sich anmelden und die Web-App nutzen oder Postman auf Ihrem Computer installieren.
In den folgenden Abschnitten erstellen Sie ein Fastify-Projekt, richten ein Datei-Upload-Plugin ein, erstellen eine /upload-Route, die mehrere Datei-Uploads verarbeiten kann, und schreiben einen Testfall für die Route.
Projekt erstellen und Fastify einrichten
Erstellen Sie zunächst ein Projekt und richten Sie Fastify ein. Wechseln Sie in das Verzeichnis, in dem Sie das Projekt erstellen möchten, und legen Sie einen Ordner namens fastify-file-upload an. Führen Sie im Terminal den folgenden Befehl aus:
Wechseln Sie in diesen Ordner:
Öffnen Sie den Ordner anschließend in Ihrem bevorzugten Code-Editor. Wenn Sie VS Code verwenden, können Sie den folgenden Befehl ausführen:
Initialisieren Sie Ihr Projekt und erstellen Sie eine package.json-Datei, indem Sie Folgendes ausführen:
Installieren Sie anschließend die Abhängigkeiten, die Sie in diesem Projekt verwenden werden:
Erstellen Sie außerdem zwei Dateien: app.js und server.js:
Die Datei app.js enthält Ihren Anwendungscode. Kopieren Sie den folgenden Code und fügen Sie ihn dort ein:
import Fastify from fastify
Dieser Code importiert das Fastify-Framework und erstellt daraus eine App-Instanz. Fügen Sie als Nächstes den folgenden Code in Ihre server.js-Datei ein:
Mit diesem Code wird Ihre Anwendung beim Ausführen bereitgestellt. Tritt dabei ein Problem auf, wird stattdessen ein Fehler zurückgegeben.
In diesem Projekt verwenden Sie die ES6-Modulsyntax. Deshalb müssen Ihre JavaScript-Dateien als Module geladen werden. Damit Ihre JavaScript-Dateien als Module geladen werden, fügen Sie in Ihrer package.json die Eigenschaft type hinzu und setzen Sie ihren Wert auf module:
Datei-Upload-Plugin einrichten
Fastify-multipart unterstützt multipart-Content-Types in Fastify. Da Sie das Plugin bereits zusammen mit den Abhängigkeiten installiert haben, können Sie es jetzt einrichten. Importieren Sie dazu multipart aus '@fastify/multipart' und registrieren Sie es anschließend.
Fügen Sie die mit + beginnenden Zeilen in Ihre app.js-Datei ein:
Hier haben Sie multipart in der zuvor erstellten Fastify-App registriert. Ihre Anwendungsinstanz kann nun multipart-Content-Types problemlos parsen.
Datei-Uploads
Es gibt mehrere Möglichkeiten, auf die Dateien einer POST-Anfrage zuzugreifen. Wenn Sie zum Beispiel wissen, dass eine Anfrage nur eine Datei enthält, können Sie mit folgendem Code darauf zugreifen:
In diesem Code ist request der Anfrageparameter der Handler-Funktion für Ihre Upload-Route. Ihre Handler-Funktion sieht etwa so aus:
Wenn Sie mehrere Dateien erwarten, rufen Sie statt file() die Methode files() auf, etwa so:
Schreiben Sie in Ihrer app.js-Datei den Code, mit dem mehrere Datei-Uploads vollständig implementiert werden. Erstellen Sie aber zunächst ein Verzeichnis, in dem die über Ihre Anwendung hochgeladenen Dateien gespeichert werden. Legen Sie dieses Verzeichnis im Stammverzeichnis Ihres Projekts an und nennen Sie es uploads:
Nehmen Sie anschließend die folgenden Änderungen an der Datei app.js vor:
Im geänderten Code haben Sie Funktionen aus den Node.js-Kernmodulen fs, util und stream importiert. Anschließend haben Sie eine /upload-Route und deren Handler-Funktion erstellt.
In der Handler-Funktion verwenden Sie req.files(), um auf alle Dateien der Anfrage zuzugreifen. Sie durchlaufen die Dateien und führen für jede Datei den Code await pump(part.file, fs.createWriteStream(`./uploads/${part.filename}`)) aus. Dadurch wird die Datei hochgeladen und im zuvor erstellten Upload-Verzeichnis gespeichert.
Beachten Sie, dass die hochgeladenen Dateien nicht erst im Arbeitsspeicher gesammelt werden, bevor sie gespeichert werden. Stattdessen erstellt die Funktion fs.createWriteStream einen Stream auf der Empfangsseite, und der Dateistream von part.file wird in den neu erstellten Stream geleitet. So wird der Dateiinhalt nicht zunächst im Arbeitsspeicher gepuffert. Stattdessen werden Datenblöcke direkt in die Zieldatei geschrieben, sobald sie den Stream durchlaufen. Das ist besonders beim Hochladen großer Dateien hilfreich. Es blockiert die Event Loop nicht und ist außerdem eine speichereffiziente Methode zur Verarbeitung von Dateien in Ihrer Anwendung.
Nun können Sie Ihren Server starten und mit Postman Dateien an ihn senden. Ersetzen Sie in Ihrer package.json-Datei das Startskript durch Folgendes:
Starten Sie den Server anschließend mit folgendem Befehl:
Wechseln Sie zu Postman und senden Sie eine POST-Anfrage an http://localhost:8000/upload. Wählen Sie im Body der Anfrage die Option form-data aus und laden Sie zwei Dateien Ihrer Wahl hoch:

Hier laden Sie eine Datei namens article.txt und eine weitere namens cover.jpg hoch (die zugehörigen Schlüssel lauten „article“ bzw. „coverImage“). Nach dem Hochladen der Dateien sollten Sie den Statuscode 200 und das Rückgabeobjekt {message : 'files uploaded' } erhalten:

Die Dateien sollten auch im zuvor erstellten Verzeichnis „upload“ zu sehen sein.
Damit haben Sie mehrere Datei-Uploads erfolgreich mit dem Plugin fastify/multipart verarbeitet. Bei den meisten Formularen müssen Sie nicht nur Dateien, sondern auch weitere Textfelder bereitstellen. Damit solche Formulare verarbeitet werden können, müssen Sie Ihren bestehenden Code so ändern, dass er sowohl Dateistreams als auch andere Felder verarbeitet.
Nehmen Sie dazu die folgenden Änderungen an Ihrer app.js-Datei vor:
Beachten Sie, dass Sie diesmal mit req.parts() sowohl auf Dateistreams als auch auf Felder zugreifen und nicht mit req.files(). Im Schleifenrumpf verwenden Sie eine if-Anweisung, um zu bestimmen, welcher Teil eine Datei ist, und Dateien anders als Felder zu verarbeiten.
Senden Sie nun eine weitere Anfrage. Speichern Sie die Datei und stoppen Sie den Server. Starten Sie ihn dann mit npm start neu. Wechseln Sie zurück zu Postman, löschen Sie die Schlüssel-Wert-Paare der vorherigen Anfrage und erstellen Sie neue. Geben Sie im ersten Feld Ihren vollständigen Namen und anschließend zwei beliebige Dateien an, wie zuvor.
Hinweis: Wenn Sie dieselben Dateien erneut verwenden möchten, sollten Sie die zuletzt hochgeladenen Dateien aus Ihrem Upload-Verzeichnis löschen.
Ihre Anfrage sollte so aussehen:

Wenn das der Fall ist, kann Ihre Anwendung jetzt mehrere Dateistreams und Felder verarbeiten.
Testfälle schreiben
Um Ihre Datei-Upload-Implementierung abzusichern, müssen Sie Tests dafür schreiben. Doch wie schreiben Sie Testfälle für Datei-Uploads in Fastify? In diesem Beispiel verwenden Sie das Test-Framework tap, das Paket form-auto-content und Fastifys .inject-Methode, um Ihre Testfälle zu schreiben.
Erstellen Sie im Stammverzeichnis Ihres Projekts die Datei app.test.js. Kopieren Sie dann den folgenden Code und fügen Sie ihn dort ein:
Ersetzen Sie die Dateipfade ./sample_files/file.txt und ./sample_files/cover.jpg durch die Pfade zu zwei beliebigen Dateien auf Ihrem Dateisystem. Oder Sie können hier Kopien dieser Dateien herunterladen.
Mit der Fastify-Methode .inject können Sie Ihrer Anwendung gefälschte HTTP-Anfragen senden, ohne den Code auf einem echten Server auszuführen. Beachten Sie im vorherigen Code, dass Sie mit formAutoContent ein Formular namens myForm erstellt und dieses Formular anschließend im Testfall als Anfragerumpf für eine gefälschte POST-Anfrage verwendet haben. Sie haben nur einen Testfall. Er erwartet, dass die Anwendung den Wert 200 für statusCode zurückgibt, wenn ein Formular mit mehreren Dateien übermittelt wird.
Führen Sie diesen Test aus und überprüfen Sie, ob er erfolgreich ist. Ersetzen Sie in Ihrer package.json-Datei das Testskript durch dieses:
Führen Sie anschließend Folgendes aus:
Der Test sollte erfolgreich sein. Die Ausgabe sollte so aussehen:

Den gesamten Code für dieses Tutorial finden Sie in diesem GitHub-Repository.
Fazit
In diesem Artikel haben Sie die Grundlagen von Datei-Uploads kennengelernt und erfahren, warum Formulare mit Dateien nur mit dem multipart/form-data content-type kodiert werden. Außerdem haben Sie zwei Möglichkeiten kennengelernt, wie Serveranwendungen Dateien verarbeiten und speichern können: in einem dedizierten Verzeichnis auf demselben Server oder in einem Cloud-Speicher wie Amazon S3. Danach haben Sie gelernt, wie Sie Uploads in Fastify verarbeiten – einem schnellen Web-Framework mit geringem Overhead für Node.js.
Wenn Sie mehr erfahren möchten, sehen Sie sich die Dokumentation zum Fastify-multipart-Plugin und den Fastify-Leitfaden zum Testen an.



