1616 Stimmen

HTML5: Bilder Upload mit Verkleinerung auf Client Seite

Tutorial von Stefan Trost | 21.09.2016 um 22:29

Bilder und Fotos werden heutzutage immer größer - oft viel zu groß, um sie vernünftig auf einer Website ausgeben zu können. Nun ist es zwar möglich, die Bilder nach dem Upload mit PHP zu verkleinern, doch dies kann sehr ressourcenaufwändig sein und sollte daher in den meisten Fällen vermieden werden.

Aus diesem Grund habe ich kürzlich in einem Tutorial beschrieben, wie man ein Bild auch ohne serverseitiges PHP-Skript direkt clientseitig im Browser verkleinern kann, um es dann bereits verkleinert an den Server zu senden. Das dort vorgestellte Skript könnte allerdings immer nur ein Bild auf einmal hochladen. Nun möchte ich in diesem Tutorial erklären, wie man mehrere Bilder auf einmal uploaden kann.

Da die Skripte hier weitestgehend dem ersten Tutorial gleichen, möchte ich hier nur auf die Änderungen eingehen und für alle anderen Erklärungen auf das erste Tutorial (oben verlinkt) verweisen. Am Ende des Tutorials findet ihr natürlich auch diesen Code in voller Länge ohne dass ihr die Stücke selber zusammen fügen müsst.

HTML

In unserem HTML ist nur eine Änderung erforderlich. Wir fügen unserem File-Input das Attribut "multiple" hinzu.

<input id="inp_files" type="file" multiple="multiple">

Dadurch erlauben wir dem Nutzer eine Mehrfachauswahl von Dateien.

JavaScript

Auch der JavaScript-Code bleibt weitestgehend identisch. Im ersten Tutorial hatten wir die Dateien mit var file = e.target.files[0] ausgelesen. Damit hatten wir nur das erste Element des Arrays e.target.files ausgelesen (das erse Element hat den Index 0).

for (var i = 0; i < e.target.files.length; i++) { 
   var file = e.target.files[i];
}

Da wir nun von einer beliebigen Anzahl von Dateien ausgehen, haben wir unseren Code um eine Schleife ergänzt, die bei 0 beginnt und die Anzahl der Dateien mit e.target.files.length berücksichtigt. Innerhalb der Schleife lesen wir dann die aktuelle Datei mit var file = e.target.files[i] aus und machen ansonsten weiter wie bisher.

document.getElementById('inp_img').value = dataURL;
document.getElementById('inp_img').value += dataURL + '|';

Während wir ersten Tutorial die Base64-codierte dataURL direkt im Feld gespeichert haben, hängen wir die Variablen nun hinten an den bestehenden Inhalt des Feldes an. Wir benutzen dafür das Trennzeichen "|", so dass wir mehrere Bilder in dem Feld speichern können.

PHP

Auch unseren PHP-Code haben wir durch eine Schleife erweitert. Zunächst benutzen wir aber die explode() Funktion, um die aneinander gehängten Bilder wieder zu trennen. Danach gehen wir mit der Schleife über alle einzelnen Einträge und speichern jedes Bild einzeln ab.

$img = explode('|', $_POST['img']);

for ($i = 0; $i < count($img) - 1; $i++) {
   $image = $img[$i];
   // ...
   $file = 'uploads/img'.date("YmdHis").'_'.$i.$ext;
   // ...    
}

Damit die Bilder später nicht alle den gleichen Namen haben und sich gegenseitig überschreiben, hängen wir außerdem noch $i als Bild-Nummer an.

Die komplette Seite

Zuletzt findet ihr hier die komplette geänderte und angepasste Seite, für den Mehrfach-Bild-Upload. Diese Seite enthält den kompletten erforderlichen HTML, PHP und JavaScript-Code.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head><body>

<?php

if (count($_POST)) {

  $img = explode('|', $_POST['img']);

  for ($i = 0; $i < count($img) - 1; $i++) {

     if (strpos($img[$i], 'data:image/jpeg;base64,') === 0) {
        $img[$i] = str_replace('data:image/jpeg;base64,', '', $img[$i]);
        $ext = '.jpg';
     }
     if (strpos($img[$i], 'data:image/png;base64,') === 0) { 
        $img[$i] = str_replace('data:image/png;base64,', '', $img[$i]);
        $ext = '.png';
     }

     $img[$i] = str_replace(' ', '+', $img[$i]);
     $data = base64_decode($img[$i]);
     $file = 'uploads/img'.date("YmdHis").'_'.$i.$ext;

     if (file_put_contents($file, $data)) {
        echo "<p>Bild $i wurde gespeichert als $file.</p>";
     } else {
        echo '<p>Bild $i konnte nicht gespeichert werden.</p>';
     }

  }
 
}

?>


<input id="inp_files" type="file" multiple="multiple">

<form method="post" action="">
  <input id="inp_img" name="img" type="hidden" value="">
  <input id="bt_save" type="submit" value="Upload">
</form>


<script>

  function fileChange(e) { 
     document.getElementById('inp_img').value = '';

     for (var i = 0; i < e.target.files.length; i++) {

        var file = e.target.files[i];

        if (file.type == "image/jpeg" || file.type == "image/png") {

           var reader = new FileReader();  
           reader.onload = function(readerEvent) {

              var image = new Image();
              image.onload = function(imageEvent) {

                 var max_size = 300;
                 var w = image.width;
                 var h = image.height;
				  
                 if (w > h) {  if (w > max_size) { h*=max_size/w; w=max_size; }
                 } else     {  if (h > max_size) { w*=max_size/h; h=max_size; } }

                 var canvas = document.createElement('canvas');
                 canvas.width = w;
                 canvas.height = h;
                 canvas.getContext('2d').drawImage(image, 0, 0, w, h);
                 if (file.type == "image/jpeg") {
                    var dataURL = canvas.toDataURL("image/jpeg", 1.0);
                 } else {
                    var dataURL = canvas.toDataURL("image/png");
                 }
                 document.getElementById('inp_img').value += dataURL + '|';
              }
              image.src = readerEvent.target.result;
           }
           reader.readAsDataURL(file);
        } else {
           document.getElementById('inp_files').value = '';
           alert('Bitte wählen Sie nur Bilder im JPG- oder PNG-Format aus.');
           return false;
        }
     }

  }

  document.getElementById('inp_files').addEventListener('change', fileChange, false);

</script>

</body></html>

Ihr könnt die Seite zum Beispiel als upload_resize_multiple.php abspeichern.

AntwortenPositivNegativDatumStimmen
55 Stimmen

Vielen Dank für diesen interessanten Beitrag - genau das was ich gesucht habe.

Die Verkleinerung funktioniert bei mir bereits bestens, mit einer Ausnahme: Teilweise kommt es vor, dass das Bild "auf den Kopf" gedreht wird. Gibt es hier eine Möglichkeit, dies zu umgehen, bzw. woran könnte das liegen?

Gruß Lukas
09.06.2018 um 21:14

AntwortenPositiv Negativ
77 Stimmen

Ich glaube nicht, dass die Drehung an diesem Script liegt.

Vermutlich liegt es an deinem Bildbetrachter / deiner Kamera. Insbesondere Handys machen es manchmal so, dass Sie alle Bilder zum Beispiel im Querformat speichern und dann nur als Metainformation dazu speichern, dass das Bild gedreht angezeigt werden soll.

Wenn du das Bild mit diesem Script bearbeitest, geht die Metainfo entsprechend verloren und das Bild zeigt sich in seiner Originaldrehung.
09.06.2018 um 23:37

Positiv Negativ
Antworten
55 Stimmen

Danke, möchte gerne 2x Upload einsetzten, leider geht nur einer?

Können Sie mir helfen?

Gruß Namrenner
20.04.2019 um 06:51

AntwortenPositiv Negativ
55 Stimmen

Ich möchte der Funktion fileChange(e) gerne unterschiedliche max_size übergeben (im Script fixiert auf 300).

Wie kann ich Werte übergeben, wo doch beim Aufruf noch nicht mal e übergeben wird?!?! Was ist das e und woher kommt es?
09.07.2019 um 21:20

AntwortenPositiv Negativ
66 Stimmen

Sehr guter Artikel.

Bei mir werden nicht alle ausgewählten Dateien übertragen. Es hängt offenbar mit der Dateigröße zusammen.
15.10.2019 um 17:14

AntwortenPositiv Negativ
44 Stimmen

Gigantisch.

Das ist eines der besten Scripte die ich je gefunden habe!

Vielen Dank!
11.02.2020 um 15:59

AntwortenPositiv Negativ
Antworten

Über den Autor

AvatarSoftware von Stefan Trost finden Sie auf sttmedia.de. Benötigen Sie eine individuelle Software nach Ihren eigenen Wünschen? Schreiben Sie uns: sttmedia.de/kontakt
Profil anzeigen

 

Ähnliche Themen

Wichtiger Hinweis

Bitte beachten Sie: Die Beiträge auf askingbox.de sind Beiträge von Nutzern und sollen keine professionelle Beratung ersetzen. Sie werden nicht von Unabhängigen geprüft und spiegeln nicht zwingend die Meinung von askingbox.de wieder. Mehr erfahren.

Jetzt mitmachen

Stellen Sie Ihre eigene Frage oder schreiben Sie Ihren eigenen Artikel auf askingbox.de. So gehts.