Lukas: Downloadlink funktioniert nicht

Hallo liebe Forumgemeinde,

auf einer Formularseite hat ein Benutzer die Möglichkeit JPG-Dateien hochzuladen. Diese speichere auf dem Linux-Server in einem speziellen Verzeichnis und speichere den Namen in einer Tabelle. Die hochgeladenen Dateien können über einen Downloadlink wieder heruntergeladen werden.

Leider funktioniert es nicht, wenn die Datei deutsche Umlaute enthält. In der Tabelle wird der Name korrekt gespeichert (bspw. Erwin_Müller.jpg) Wenn ich mir das Verzeichnis über WinSCP anschaue, wird auch dort der Name korrekt angezeigt. Aber schaue ich mir das in einer Putty-Session an, wird dort Erwin_M?ller.jpg angezeigt. Beim Klick auf den Download-Link erscheint im Browser schlicht "Objekt nicht gefunden".

Muss ich zwangsweise vor dem Upload alle deutschen Umlaute und sonstige Sonderzeichen ersetzen oder gibt es noch eine andere Möglichgkeit die Datei mit den Original-Umlauten wieder herunterzuladen?

Vielen Dank für Eure Unterstützung,

Lukas

  1. Moin Lukas,

    auf einer Formularseite hat ein Benutzer die Möglichkeit JPG-Dateien hochzuladen. Diese speichere auf dem Linux-Server in einem speziellen Verzeichnis und speichere den Namen in einer Tabelle. Die hochgeladenen Dateien können über einen Downloadlink wieder heruntergeladen werden.

    dazu habe ich direkt ein paar Fragen:

    1. Wie stellst du sicher, dass nur JPEG-Dateien hochgeladen werden können?
    2. Kann jeder Nutzer die Dateien herunterladen oder nur derjenige, der eine Datei hochgeladen hat?

    Hintergrund: Wenn du einen offenen Upload-Bereich hast, wird der sehr schnell zum Austausch illegaler Inhalte missbraucht.

    Leider funktioniert es nicht, wenn die Datei deutsche Umlaute enthält.

    … vermutlich nicht nur bei deutschen Umlauten …

    In der Tabelle wird der Name korrekt gespeichert (bspw. Erwin_Müller.jpg) Wenn ich mir das Verzeichnis über WinSCP anschaue, wird auch dort der Name korrekt angezeigt. Aber schaue ich mir das in einer Putty-Session an, wird dort Erwin_M?ller.jpg angezeigt. Beim Klick auf den Download-Link erscheint im Browser schlicht "Objekt nicht gefunden".

    Muss ich zwangsweise vor dem Upload alle deutschen Umlaute und sonstige Sonderzeichen ersetzen oder gibt es noch eine andere Möglichgkeit die Datei mit den Original-Umlauten wieder herunterzuladen?

    Du musst sicherstellen, dass alle Beteiligten die gleiche Zeichenkodierung sprechen:

    • Upload-Formular
    • Datenbank
    • Dateisystem
    • Download-Skript

    Viele Grüße
    Robert

    1. Hallo Robert,

      vielen Dank für die schnelle Antwort. Hochladen kann jeder und herunterladen dann auch. Ich prüfe beim Upload, ob die Dateiendung .jpg lautet und ob der Dateiheader eine JPG-Datei ist. Spezielle Sonderzeichen (Anführungsstriche, Slash, Backslash, Hochkomma) prüfe ich auch. Der Server ist aber von außen nicht erreichbar.

      Ich weiß eben nicht wo, ein Beteiligter nicht die gleiche Zeichenkodierung spricht und wie ich das korrigieren könnte.

      In der Datenbank-Tabelle wird er richtig angezeigt. Ebenso bei der Anzeige des Namens im Link auf der Webseite und im Link-Target. Im WinSCP wird der Name auch auf dem Server richtig angezeigt. Nur über Putty nicht.

      Gibt es noch die Chance, die Datei nachträglich "herunterladbar" zu machen ohne sie umzubenennen?

      Lukas

      1. Hallo @all,

        ich habe die Antwort selber gefunden:

        Mit einem urlencode($dateiname) kann ich die hochgeladene Datei mit deutschen Umlauten wieder korrekt herunterladen.

        Danke,

        Lukas

        1. Moin Lukas,

          ich habe die Antwort selber gefunden:

          Mit einem urlencode($dateiname) kann ich die hochgeladene Datei mit deutschen Umlauten wieder korrekt herunterladen.

          Das liest sich danach, als sei vorher

          • der HTML-Code für den Link nicht sicher gewesen, z.B. <a href=> statt <a href="">
          • oder im Dateinamen sind Zeichen enthalten, die im HTML-Kontext nicht korrekt maskiert worden sind (", &< und > kann eigentlich ausschließen).

          Viele Grüße
          Robert

      2. Moin Lukas,

        Spezielle Sonderzeichen (Anführungsstriche, Slash, Backslash, Hochkomma) prüfe ich auch.

        An welcher Stelle findet diese Prüfung statt und mit welchem Ziel?

        Der Server ist aber von außen nicht erreichbar.

        OK, das reduziert das Risiko.

        Ich weiß eben nicht wo, ein Beteiligter nicht die gleiche Zeichenkodierung spricht und wie ich das korrigieren könnte.

        Du legst es fest:

        • im Upload-Formular: <meta charset="utf-8">
        • in der Datenbank durch Angabe der Collation/des Zeichensatzes
        • Das Dateisystem hat häufig einen bestimmten Zeichensatz:
          • unter Linux/Unix/macOS UTF-8
          • unter Windows UCS-2 (NTFS)
        • im Download-Skript: <meta charset="utf-8">
        • im Download-Link: <a href=""> und durch Beachten des Wechsel in den URL-Kontext

        In der Datenbank-Tabelle wird er richtig angezeigt. Ebenso bei der Anzeige des Namens im Link auf der Webseite und im Link-Target. Im WinSCP wird der Name auch auf dem Server richtig angezeigt. Nur über Putty nicht.

        Welchen Zeichensatz verwendet PuTTy denn?

        Viele Grüße
        Robert

        1. @@Robert B.

          des Zeichensatzes … einen bestimmten Zeichensatz … Welchen Zeichensatz

          Unicode. Der Zeichensatz dürfte in allen Fällen Unicode sein.

          Du meinst Zeichencodierung?

          Merke: charset steht nicht für Zeichensatz, sondern für Zeichencodierung. What a charset!

          🖖 Живіть довго і процвітайте

          --
          Ad astra per aspera
    2. @@Robert B.

      Du musst sicherstellen, dass alle Beteiligten die gleiche Zeichenkodierung sprechen:

      Und diese sollte UTF-8 sein.

      🖖 Живіть довго і процвітайте

      --
      Ad astra per aspera
  2. Hallo

    auf einer Formularseite hat ein Benutzer die Möglichkeit JPG-Dateien hochzuladen. Diese speichere auf dem Linux-Server …. Die hochgeladenen Dateien können über einen Downloadlink wieder heruntergeladen werden.

    Leider funktioniert es nicht, wenn die Datei deutsche Umlaute enthält.

    Die vordergründige Antwort, den Strings/die Zeichenketten mit der Pfadangabe zu behandeln, hast du ja selbst gefunden. Allerdings ist zu beachten, wo der Dateiname innerhalb der URL angegeben wird. Ist der Dateiname Teil des Pfades der URL selbst (also zum Beispiel https://www.example.org/download/beispiel.jpg), ist dafür die Funktion rawurlencode zu benutzen und nicht urlencode.

    Die von dir gefundene Funktion urlencode benutzt man, wenn der String (bei dir der Dateiname) Teil eines URL-Parameters ist (also zum Beispiel https://www.example.org/download.html?download=beispiel.jpg). Hier ist download der Parameterschlüsselname und beispiel.jpg der mit urlencode zu behandelnde Wert.

    Siehe dazu auch die Handbuchseinten zu rawurlencode und urlencode.

    Wie Robert schon schrieb, ist aber auch wichtig, alle Speicher-, Verarbeitungs- und Ausgabeschritte mit der selben Kodierung auszuführen und wie Gunnar schrieb, sollte das die Kodierung UTF-8 sein und nix anderes.

    Das betrifft also die Seite mit dem Formular zum Upload, das Skript, dass den Upload verarbeitet, prüft, speichert und den zugehörigen Datenbankeintrag erzeugt, die Datenbank selbst und die Verbindungen zum schreiben in und lesen aus der Datenbank, das Skript, dass aus der Datenbank liest und die Ausgabe der Seite, auf der sich der Downloadlink befindet, erzeugt und schlussendlich wieder der Webserver, der diese Seite an die Browser ausliefert.

    Ähhh … und es betrifft auch das Programm, mit dem du die Skripte schreibst (Texteditor oder IDE). Das sieht nach viel Hassle aus, aber im Grunde musst du das einmal abklären, enrichten und/oder einstellen.

    Und kurz vor dem Ende dieser Kette, bei der Erstellung der HTML-Ausgabe, müssen alle von außerhalb des Skripts kommenden Zeichenketten, die Teil der Ausgabe werden sollen, gemäß ihren Kontextes maskiert werden. Text, der sichtbar auf der HTML-Seite ausgegeben werden soll, muss mit htmlspecialchars behandelt werden, URL …

    [edit]
    vorhin vergessen, den Satz zu beenden:
    … -Bestandteile, je nach Anwendungsfall, mit rawurlencode oder urlencode.
    [/edit]

    Tschö, Auge

    --
    „Habe ich mir das nur eingebildet, oder kann der kleine Hund wirklich sprechen?“ fragte Schnapper. „Er behauptet, nicht dazu imstande zu sein“ erwiderte Victor. Schnapper zögerte (…) „Nun …“ sagte er schließlich, „ich schätze, er muss es am besten wissen.“ Terry Prattchett, Voll im Bilde
  3. Muss ich zwangsweise vor dem Upload alle deutschen Umlaute und sonstige Sonderzeichen ersetzen oder gibt es noch eine andere Möglichgkeit die Datei mit den Original-Umlauten wieder herunterzuladen?

    Just my 2 Cents zum Thema, auch wenn ich dafür Prügel zu erwarten habe: lass dass mit dem Unicode im Filesystem einfach. Ja, auch 2023 noch. Es gibt da viele, fiese Fallstricke. "Webinhalte" sollten heutzutage natürlich den kompletten Zeichensatz unterstützen, ja.

    Bei Dateinamen kann man das m.E. pragmatischer sehen und drauf pfeifen. Dann bestehen die halt nur aus einem reduzierten Zeichensatz. So what.

    Wenn Du ganz korrekt unterwegs sein willst, dann liefer das File halt via HTTP / PHP (or whatever) aus, dann kannst Du aus der DB den favorisierten Dateinamen ja mitgeben. Den hast Du dann ja lt. Datenbank griffbereit. Aber im Dateisystem selbst würde ich da weiterhin einfach die Finger von lassen.

    Spätestens wenn da irgendein exotischer Storage ins Spiel kommt: viel Spaß.

    1. @@Mitleser 2.0

      auch wenn ich dafür Prügel zu erwarten habe: lass dass mit dem Unicode im Filesystem einfach.

      Anstatt dich zu prügeln, ignoriere ich deinen Ratschlag einfach. 😆

      Aber ja:

      Es gibt da viele, fiese Fallstricke.

      Einer macht mir auch zu schaffen: Wenn ich eine Datei auf meinen Webserver hochlade, dann hat die dort bspw. weltraumfähren im Namen – das ä decomposed: U+0061 U+0308. (Möglicherweise, weil mein lokales OS Dateinamen so handhabt?) Der Aufruf der Webseite funktioniert nicht.

      Ich muss das umbenennen in weltraumfähren – das ä precomposed: U+00E4. Dann geht’s. Bzw. fliegt. 🚀

      🖖 Живіть довго і процвітайте

      --
      Ad astra per aspera
      1. Aber ja:

        Es gibt da viele, fiese Fallstricke.

        Einer macht mir auch zu schaffen: Wenn ich eine Datei auf meinen Webserver hochlade, dann hat die dort bspw. weltraumfähren im Namen – das ä decomposed: U+0061 U+0308. (Möglicherweise, weil mein lokales OS Dateinamen so handhabt?) Der Aufruf der Webseite funktioniert nicht.

        Ich muss das umbenennen in weltraumfähren – das ä precomposed: U+00E4. Dann geht’s. Bzw. fliegt. 🚀

        Wenn das für dich so passt: supi. Ich bleibe bei meiner These: im Dateisystem würde ich das nach Möglichkeit einfach vermeiden wollen. Zu viel potentieller Trouble. Soweit ich in der Datenbank den "gewünschten" Dateinamen zur Hand habe, ist doch alles fein. Dann kann ich das File "fruehstueck_MD5.jpg" ja auch gerne als "早餐拼写.jpg" ausliefern, wenn ich mag. Fertig.

        Der Informationsgehalt des Dateinamens selbst ist doch eh beschränkt.

      2. Hallo

        Es gibt da viele, fiese Fallstricke.

        Einer macht mir auch zu schaffen: Wenn ich eine Datei auf meinen Webserver hochlade, dann hat die dort bspw. weltraumfähren im Namen – das ä decomposed: U+0061 U+0308. (Möglicherweise, weil mein lokales OS Dateinamen so handhabt?) Der Aufruf der Webseite funktioniert nicht.

        Mac-Server?

        Ich muss das umbenennen in weltraumfähren – das ä precomposed: U+00E4. Dann geht’s. Bzw. fliegt. 🚀

        Schön auch Zeichen, die, abhängig vom Dateisystem, in Dateinamen verboten sind. Da kommen auch Rolfs Aussagen zum Umgang mit Dateinamen ins Spiel, auch wenn er auf andere Aspekte zielt.

        Als nicht gar so abwegiges Beispiel seien Zeitstempel in Dateinamen genannt. In unixoiden Systemen (wie zum Beispiel eben Unix selbst, Linux oder MacOS) kann man einen Dateinamen wie 2023-10-16-12:33:45.txt bilden. Die Doppelpunkte sind aber in Windows in Dateinamen nicht zulässig. Mein FTP-Programm geht damit um, indem es die Doppelpunkte URL-maskiert und durch %3A ersetzt.

        Auch in der Weboberfläche von NextCloud lassen sich derart benannte Dateien unter Windows herunterladen. Hier werden die Doppelpunkte durch Leerzeichen ersetzt. Das funktioniert in beiden Fällen störungsfrei, auch wenn es im Zweifelsfall unschön aussieht.

        Der NextCloud-eigene Desktop-Client hingegen, der die Dateien eines NextCloud-Servers auf den lokalen Rechner synchronisieren soll, bricht, wenn er zu einer solchen Datei kommt, die Synchronisation des entsprechenden NextCloud-Accounts mit einer Fehlermeldung komplett ab. Da man auf der Seite des lokalen Rechners nichts ausrichten kann, muss man auf die Serverseite, um das Problem zu beheben.

        Und man muss zuvor drauf kommen, was nun konkret die Ursache des Problems ist. Die Fehlermeldung von NextCloud ist zwar ausführlicher, als es eine vergleichbare Fehlermeldung von MS typischerweise ist, aber trotzdem hat man gute Chancen, erst einmal fünf Minuten einfach nur wie das sprichwörtliche Schwein, das sich ein Uhrwerk zu Gemüte führt, auf den Bildschirm zu starren, bevor es Klick macht.

        Tschö, Auge

        --
        „Habe ich mir das nur eingebildet, oder kann der kleine Hund wirklich sprechen?“ fragte Schnapper. „Er behauptet, nicht dazu imstande zu sein“ erwiderte Victor. Schnapper zögerte (…) „Nun …“ sagte er schließlich, „ich schätze, er muss es am besten wissen.“ Terry Prattchett, Voll im Bilde
  4. Hallo Lukas,

    ich kann Dir nur davon abraten, vom Benutzer eingegebene Zeichenketten als Dateiname auf deinem Server und in URLs zu verwenden. Besser ist es, den Dateinamen nur als beschreibendes Attribut zu verwenden und auf deinem Server generierte künstliche Dateinamen zu nutzen. Solche Namen dürfen nicht ratbar sein, d.h. eine fortlaufende Nummerierung ist falsch. Die Namen sollten lang sein (bspw. 64 Stellen) und müssen zufällig erscheinen. Du könntest beispielsweise ein Pfund Salz nehmen (einen beliebigen String, der mind. 64 Zeichen hat), den vom User gelieferten Namen anhängen, dann noch den aktuellen Timestamp und einen 384-bittigen Hash daraus machen. Dessen base64-Darstellung wäre dann 64 Zeichen lang.

    Je nach Schutzstatus, den die JPGs haben, ist es aber generell ungeschickt, direkte Links in das Upload-Verzeichnis zu setzen. Wenn nämlich User A Zugriff auf 1.JPG haben soll, der User B aber nicht, dann wäre es doof, wenn User B nur dadurch, dass er zufällig den Namen errät oder ausspioniert, die Datei abrufen kann.

    Wenn eh jeder alles sehen darf, ist die Lage entspannter.

    Aber eigentlich sollte man den Download über ein zwischengeschaltetes PHP lösen, das prüft, ob der Abrufer diese Datei lesen darf und nur bei vorliegender Berechtigung die Datei in die HTTP Response kopiert. Dieses PHP kann dann auch die Datei-ID in den technischen Dateinamen auf deinem Server übersetzen.

    Rolf

    --
    sumpsi - posui - obstruxi