Slim 3 – Datei Upload via Javascript + Axios

Tutorial Slim

von Ardian Shala, 11.02.2018 - update: 21.03.2018
Der Datei Upload erfolgt mittels Javsacript Client.
Hierbei dient eine einfache HTML Datei, die in der Funktion "window.onload" einen EventListener zum Input vom Typ "file" hinzufügt.
Vorraussetzung:
  • Slim Framework - link
  • Axios - link
  • Verständnis JS File Object - link

Javascript Upload Client erstellen

Der Datei Upload erfolgt mittels Javsacript Client.
Hierbei dient eine einfache HTML Datei, die in der Funktion window.onload einen EventListener zum Input vom Typ file hinzufügt.
Wird eine Datei ausgewählt, so feuert das Event change.
In der Callback Funktion von change wird als Parameter das Event des Input übergeben.
Eine einzelne Datei lässt sich mittels event.target.files[0] abrufen, welche später an die Funktion uploadFile übergeben wird.

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <input id="fileUpload" type="file" />
    </body>
    <script>
        window.onload = () => {
            let fileUpload = document.querySelector("#fileUpload");
            fileUpload.addEventListener("change", (event) => {
                uploadFile(event.target.files[0])
            });
        }
    </script>
</html>

Axios integrieren

Axios ist eine Thrid Party Library, welche Promise-basiert aufgebaut ist und das Arbeiten mit REST Schnittstellen vereinfacht.
Axios lässt sich wie folgt über ein CDN in die index.html integrieren.

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Javascript Upload Funktion implementieren

Nun wird die Funktion „uploadFile“ ausimplementiert, welche als Parameter genau eine Datei vom Typ File erwartet.
Mittels FormData Objekt, welches Schlüssel-Wert Paare erwartet, lässt sich die Datei mit einem Key (hier „file“) hinzufügen.

uploadFile(file) {
    let formData = new FormData();
    formData.append('file', file);
    const config = { headers: { 'content-type': 'multipart/form-data' } }
    axios.post('http://localhost/slim-api/public/upload-file', formData, config);
}

Cors aktivieren

Damit Programme außerhalb der API auf die Routen zugreifen können, muss Access-Control-Allow-Origin serverseitig aktiviert werden.
Weiteres kann auf der Slim Seite nachgelesen werden: Link

//vor allen Routes angeben
$app->options('/{routes:.+}', function ($request, $response, $args) {
    return $response;
});

$app->add(function ($req, $res, $next) {
    $response = $next($req, $res);
    return $response
            ->withHeader('Access-Control-Allow-Origin', '*') //dies gewährleistet den Zugriff für alle extere Programme und sollte nur zur Entwicklung genutzt werden
            ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
            ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});

//... eigene Routes

//nach allen Routes angeben
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function($req, $res) {
    $handler = $this->notFoundHandler; // handle using the default Slim page not found handler
    return $handler($req, $res);
});

Slim Api Upload Route definieren

Nun fügen wir die Route upload-file hinzu.
Hochgeladene Dateien lassen sich in der Callback Funktion über das $request Objekt abfragen.
Untenstehend lesen wird diese aus und schreiben sie in $files.

$app->post("/upload-file", function(Request $request, Response $response){
    $files = $request->getUploadedFiles();
});

Datei speichern

Nun ergänzen wir die obenstehende Funktion.
Enthält „$files“ kein Key mit der Bezeichnung „file“ ist etwas schiefgegangen.
1. File auslesen
2. Dateiname aus File auslesen
3. Nur im Fall von „Upload_ERR_OK“ weiter machen
4. Verzeichnis erstellen, falls nicht vorhanden
5. Datei zum Ziel verschieben (hier „assets“)

if (empty($files['file']))
    throw new \RuntimeException('Expected a newfile');

    $file = $files['file'];

    if ($file->getError() === UPLOAD_ERR_OK) {
        $fileName = $file->getClientFilename();

            //Pfad erstellen, falls nicht vorhanden
            if(!is_dir("../assets"))
                    mkdir("../assets");

            $file->moveTo("../assets/{$fileName}");

            return $response
                    ->withJson(['result' => ['fileName' => $fileName]])
                    ->withStatus(200);
    }

    return $response
            ->withJson(['error' => 'Nothing was uploaded'])
            ->withStatus(415);

Fazit

Mittels Javascript Client, gepaart mit Axios und das Verwenden von dem Javascript Objekten „File“ und „FormData“, lässt sich eine Datei clientseitig einfach vorbereiten und an eine API Schnittstelle senden.
SlimFramework dient hierbei als die API, die das Abfragen der hochgeladenen Datei(en) erleichtert.

#axios #file #fileupload #formdata #javascript #php #slim #slimframework

Autor: Ardian Shala

Ersteller der Webseite MuchaDev. Selbstständiger IT Constultant für Frontend Technologien.