Upload-Routine (Forum)

Kategorie Webentwicklung
2. Kategorie uf
Inhalt
Vor fast drei Jahren hielt ich es für eine gute Idee, dem Forum eine neue Upload-Seite zu geben. Die Idee an sich war ja gar nicht so falsch, aber die Ausführung war langfristig etwas problematisch.

Die Idee war, möglichst viel in Javascript im Browser des Benutzers zu erledigen:
  • verkleinern
  • nachschärfen
  • Ausschnitt wählen.

damit (a) man auch ohne irgendwelche Hilfsmittel/Programme ein Bild rein stellen kann, (b) mehrere Bilder gleichzeitig hoch laden kann (was für das Forum deaktiviert war), (c) ich irgendwann, wenn das alles gut genug getestet ist, einen Haufen alten Code in der server-seitigen Software los werden kann, und (d) das Leben der Leute, die mit mobilen Geräten etwas hochladen wollen, etwas einfacher würde.

Ich meine, wie schwer kann das schon sein? Für Verkleinern/Nachschärfen funktioniert pica.js ziemlich gut, für die Ausschnittswahl nimmt man Cropper (kannte ich schon, und taugt für den Zweck), und piexifjs kann man benutzen, um die Exif-Daten im Browser auszulesen. Kann ja nur ein Kinderspiel sein…

Na ja, das war es nicht, denn im Javascript-Umfeld arbeitet einfach nichts so zusammen, wie man das wünscht. Die eine Funktion erwartet ein image- oder canvas-Element, die Nächste braucht zwangsweise ein canvas, die Dritte ein image, und die Letzte will dann ein Uint8Array. Über die Programmstruktur, die einem das aufzwingt, fällt mir gerade nichts Positives ein.


Nebensächlicher Einschub: Javascript ist in meinen Augen ein Stück Dreck aus der EDV-Steinzeit.
  • eine ereignis-gesteuerte Sprache, bei der Ereignisse und Callbacks keinem Standard gehorchen, und Programmierer an vielen Stellen globalen Status von Hand flicken müssen, um eine klassische Event-Loop verwenden zu können, und dann meint jede kleine Bibliothek da wieder irgendetwas Anderes zurück liefern zu dürfen. Da durfte ich an allen Ecken und Enden (ja, allen) zwischen image, canvas, Blobs, ArrayBuffer und Uint8Arrays konvertieren. Warum?
  • warum eine so triviale Funktion wie das Laden eines Bildes einen Callback braucht (manuell auszulösen, wenn das Bild schon im Browsercache ist), verstehe ich nicht. Warum? Weil die Browserhersteller in 10 oder 20 Millisekunden so tun wollen, als sei der Browser fertig? Warum? Der Benutzer wartet in jedem Fall 3 Minuten, wenn das Bild ein paar Gigabyte groß ist. Mehr kann der in der Zeit nicht tun…
    In *jeder* anderen Sprache ist das Laden eines Bildes trivial, und dann hat man auch irgendetwas, womit man direkt arbeiten kann. In Javascript fängt man danach erst mal an, die Bilddaten dann erst mal zu konvertieren.
Ich breche an der Stelle mal ab, bevor ich mich noch darüber auslasse, wie toll ich es finde, im Jahr 100 neue APIs dazu zu tun, die nie dazu gedacht worden sind, miteinander zusammen zu arbeiten.

Ich hatte es zum Laufen bekommen. Mit einer Einschränkung, die mich immer gestört hat: Das Exif-Handling bei Bildern, die bereits auf dem Server waren (z.B. wegen Abbruch des Uploads zu einem blöden Zeitpunkt), funktionierte nie. Das war eine Limitation der verwendeten Exif-Library, für die es keinen sauberen Workaround gab.
Das war nicht schön, aber damit konnte ich leben.

So weit, so gut. Mit der Zeit kam Feedback. Erst weitgehend Positives, aber mit Zeit kamen da ein paar Sachen rein, die weniger gut waren.
  1. Beispielsweise gab es offenbar Qualitätsunterschiede zwischen mit unterschiedlichen Browsers hoch geladenen und verkleinerten Bildern. Das konnte aber nicht sein, die Bibliothek hat immer dasselbe getan. Es war aber so: Derselbe Code hat auf unterschiedlichen Browsern Jpeg unterschiedlicher Qualität erzeugt. Genau, es war gar nicht die Verkleinerung - es war die in dem Fall nötige Jpeg-Kompression. Workaround: anderen Browser nehmen :-( Es ist aber nicht unbedingt mein Wunsch, den Benutzern zu sagen, welche Browser ihnen zu gefallen haben (sie sind alle Scheiße).
  2. Dann hatte jemand Probleme mit der Ausschnittswahl… ja, dicke Finger und Tablets - keine gute Kombination. Gute Workaround: keine (die hatten für Andere Nachteile). Nur war bessere Mobilgeräteunterstützung durchaus ein Ziel gewesen.
  3. dann war das Exif-Handling immer ein Problem. So lange die Exifs so ungefähr dem Standard entsprechen, war alles OK. Aber wehe wenn nicht - dann fiel die Bibliothek auf die Nase. Und das nicht mal so, dass mal sinnvoll hätte abfangen können (jedenfalls nicht so, dass man irgendetwas Sinnvolles hätte tun können). Die Fehlerbehandlung ist ziemlich grottig gewesen. Eine Weile habe ich gewartet, ob sich da von Seiten der Programmierer etwas tut, aber es tat sich nichts - die arbeiten seit Jahren an Version 2.0, bei der 1er-Version tut sich nichts mehr, und die 2er ist nicht brauchbar.
  4. was passiert, wenn man ein irrsinnig großes Bild (Gigapixel) mit seinem iPhone im Browser auf 800x600 verkleinern will ist dieses: Der Akku leert sich schnell. Fertig wird das Gerät nicht (auch nicht am Ladekabel, weil irgendwann der Speicher alle ist). Android ist da übrigens nicht wirklich besser, es hat nur früher keinen Speicher mehr frei. An sich ist das nicht weiter schlimm, denn wer außer meinem Kumpel Ingo macht so einen Blödsinn? Aber Ingo hat dann mal tiefer da rein geschaut, und festgestellt, dass der Akkuverbrauch tatsächlich ein Problemchen ist (mit 50 Megapixel großen Bildern ist es messbar, aber nicht wirklich schlimm), aber der Speicherverbrauch ein echtes Problem ist, einfach weil bei den vielen Konvertierungen zwischen den Datentypen eine Menge Zeug im Speicher blieb, bis die Seite neu oder eine andere Seite geladen wurde. Und das war auch noch je nach Browser anders… Das fällt im Kontext des Forums nicht so auf, weil wir da nur einen Bildupload gleichzeitig erlauben, aber für Ingo war das durchaus doof, er will damit eben mal fünf oder auch zehn Bilder hochladen, und da knallte es schon (er hat so ein überzüchtetes Smartphone für unglaublich vielen Pixel und unangemessen wenig Speicher).
  5. wegen (1) und (3) konnte ich den alten Forums-Code zu Verkleinerung der Bilder nie löschen - der wurde als Workaround gebraucht.

Wie viele meiner Ziele habe ich also erreicht?

(a) [ohne Hilfsmittel/Programme ein Bild hochladen]: eingeschränkt.
(b) [mehrere Bilder gleichzeitig]: für den, für den es gedacht war, nicht.
(c) [alten Code loswerden]: Nein.
(d) [besserer Support für Mobilgeräte]: Hm. Ja, ein bisschen.
Sagen wir, 33%? Positiv geschätzt?

Aber:
- ich habe jetzt zwei Uploadroutinen zu pflegen. Das ist mehr Code statt weniger.
- ich habe jetzt schon einige Workarounds für alte Browser im neuen Uploader.
- der neue Code hat bekannte Einschränkungen, die ich nur mit Code im Server umgehen könnte.

Das war's nicht, und deshalb ist die neue Upload-Routine jetzt Geschichte.
Diashow
Blog