Franz Kruse: File-Upload mit festem Dateinamen

Kann mir jemand auf die Sprünge helfen, wie ich Folgendes möglichst einfach realisiere:

Ich möchte eine Datei hochladen und dazu ein Formular der Art

<form action="..." method="POST" enctype="multipart/form-data">
      <input type="HIDDEN" name="xyz" value="...">
      ... mehrere versteckte Felder ...
      <input type="FILE" name="file">
   </form>

verwenden. Für die zu verschickende Datei soll jedoch kein Dateiauswahl-Menü erscheinen, sondern das Formular soll vollständig unsichtbar sein. Es soll eine bestimmte Datei mit festem Dateinamen versteckt verschickt werden. Das Feld

<input type="FILE" name="file">

müsste also durch etwas Geeignetes ersetzt werden. Gibt es dafür eine einfache Lösung?

  1. Hoi.

    verwenden. Für die zu verschickende Datei soll jedoch kein Dateiauswahl-Menü erscheinen, sondern das Formular soll vollständig unsichtbar sein. Es soll eine bestimmte Datei mit festem Dateinamen versteckt verschickt werden.

    Du meinst vermutlich sowas hier:

    <input type="FILE-invisible" name="file" value="c:\privat\homebanking_pin_und_tan.txt">

    Klingeling?

    Grüße

    1. Du meinst vermutlich sowas hier:

      <input type="FILE-invisible" name="file" value="c:\privat\homebanking_pin_und_tan.txt">

      Klingeling?

      So etwas, ja. Natürlich nicht für den von dir spöttisch angedeuteten Zweck, sondern für etwas durchaus Vernünftiges. Ich möchte eine Zip-Datei (deren Inhalt der Benutzer auf anderem Wege bestimmt hat) zusammen mit einigen anderen Werten per Multipart-Message verschicken. Dafür könnte ich selbst eine Multipart-Message zusammenbauen und verschicken, einfacher und lesbarer ginge es aber, wenn man die Hauptarbeit vom Formular machen lassen und die Datei irgendwie dazupacken könnte.

      1. So etwas, ja. Natürlich nicht für den von dir spöttisch angedeuteten Zweck, sondern für etwas durchaus Vernünftiges.

        Mit dem "spöttisch angedeutem Zweck" im Hinterkopf, würdest Du einen Browser benutzen, _der_ es ermöglicht?

        Grüße

  2. Ich hätte noch dazusagen sollen, dass die zu verschickende Datei auf dem Server liegt. Es soll also nicht, wie bei

    <input type="FILE" ...>

    eine Datei vom Client verschickt werden.

    1. Hi,

      Ich hätte noch dazusagen sollen, dass die zu verschickende Datei auf dem Server liegt. Es soll also nicht, wie bei
         <input type="FILE" ...>
      eine Datei vom Client verschickt werden.

      Ja, das haettest du vielleicht dazusagen sollen - dann haette man dir gleich antworten koennen, dass du mit einem clientseitigen Formular an der ganz falschen Adresse bist.

      Wenn die Datei bereits auf dem Server vorliegt, wozu soll sie denn dann noch "hochgeladen" werden?

      Wenn die Datei auf dem Server liegt, dann ist es auch an ihm, sie ggf. irgendwohin zu verschicken - und nicht am Client.

      MfG ChrisB

      --
      „This is the author's opinion, not necessarily that of Starbucks.“
      1. Wenn die Datei auf dem Server liegt, dann ist es auch an ihm, sie ggf. irgendwohin zu verschicken - und nicht am Client.

        Natürlich. Sie soll, so wie die übrigen Formulardaten auch, an eine andere URL verschickt werden.

        1. Moin!

          »» Wenn die Datei auf dem Server liegt, dann ist es auch an ihm, sie ggf. irgendwohin zu verschicken - und nicht am Client.

          Natürlich. Sie soll, so wie die übrigen Formulardaten auch, an eine andere URL verschickt werden.

          Das ist gerade das Problem: Wenn die übrigen Formulardaten im Browser eingegeben werden, und die Datei auf dem einen Server liegt, dann kann die Datei nicht so, wie die übrigend Formulardaten verschickt werden.

          Ich nehme einfach mal an, dass es dir nicht um den Trivialfall geht, dass die Formulardaten im Client und die Datei auf dem einzigen beteiligten Server liegt, und nun beides auf wieder diesen einzigen Server, aber anderswo hin gelangen soll.

          Einzige Möglichkeit: Schicke die Formulardaten dorthin, wo die Datei liegt, und schicke dann alles zusammen dorthin, wo es enden soll. Das geht nicht von selbst, aber es gibt zahlreiche Beispielskripte für das programmgesteuerte Generieren von HTTP-POST-Requests - da sollte eines dabei sein, dass paßt.

          Ein Mischen von clientseitigem Formularinhalt mit der Datei irgendeines Servers zu einem gemeinsamen Request, der auf einen ganz anderen Server gehen soll, ist nicht möglich, weil der Server mit der Datei in den Request, welcher die Formulardaten sendet, gar nicht mehr eingebunden ist. Er kriegt also nicht mit, dass das Formular abgeschickt wurde, und kann dementsprechend auch nicht sagen "Hier ist noch die zugehörige Datei".

          Natürlich kann man Mechanismen programmieren, die über ein wechselseitiges Hin- und Herverschieben der Daten bzw. von Benachrichtigungen über eingetroffene Dateien oder Formulare in weiteren Requests regeln, dass am Ende alle Informationen am Ziel sind - das ist aber definitiv nicht trivial, zumal auch die Sicherheit zu beachten ist.

          - Sven Rautenberg

          1. Einzige Möglichkeit: Schicke die Formulardaten dorthin, wo die Datei liegt, und schicke dann alles zusammen dorthin, wo es enden soll. Das geht nicht von selbst, aber es gibt zahlreiche Beispielskripte für das programmgesteuerte Generieren von HTTP-POST-Requests - da sollte eines dabei sein, dass paßt.

            Das ist natürlich ein naheliegender Ansatz. Leider geht er bei mir nicht. Das Verschicken der Datei an einen zweiten Server muss beim Benutzer ein Fenster aufklappen, in dem er sich typischerweise erst einmal anmelden und dann die weiteren Schritte bestätigen muss.

            Daher war meine Idee, vom ersten Server aus eine Antwort an den Benutzer zu schicken, in dem die Datei Base64-kodiert in einem versteckten Formular enthalten ist und als ACTION eine URL auf dem zweiten Server angegeben ist. Das Submit zu diesem Formular wird automatisch ausgelöst, die Daten werden zum zweiten Server übertragen, dieser baut seine Antwortseite, so wie gewünscht, beim Benutzer auf. - Nur: Wie baut man dieses versteckte Formular auf?

            Der Nachteil dieses Verfahrens ist natürlich, dass die Datei zweimal übertragem wird: Server 1 -> Browser -> Server 2. Aber ich habe keinen Weg gefunden, dies zu vermeiden.

            1. Hi,

              Das ist natürlich ein naheliegender Ansatz. Leider geht er bei mir nicht. Das Verschicken der Datei an einen zweiten Server muss beim Benutzer ein Fenster aufklappen, in dem er sich typischerweise erst einmal anmelden und dann die weiteren Schritte bestätigen muss.

              Bei wem muss sich der Benutzer anmelden, bei Server 1 oder Server 2?

              Daher war meine Idee, vom ersten Server aus eine Antwort an den Benutzer zu schicken, in dem die Datei Base64-kodiert in einem versteckten Formular enthalten ist und als ACTION eine URL auf dem zweiten Server angegeben ist. Das Submit zu diesem Formular wird automatisch ausgelöst, die Daten werden zum zweiten Server übertragen, dieser baut seine Antwortseite, so wie gewünscht, beim Benutzer auf. - Nur: Wie baut man dieses versteckte Formular auf?

              Na mit HTML ...
              Hidden Field, kodierte und ggf. entsprechend maskierte Daten ins value-Attribut reinschreiben.
              Automatisches Abschicken auf dem Client per JavaScript.

              Der Nachteil dieses Verfahrens ist natürlich, dass die Datei zweimal übertragem wird: Server 1 -> Browser -> Server 2.

              Ja, das ist ein ziemlich massiver Nachteil.
              Der Client muss die komplette Datei erst mal empfangen - und dann auch noch wieder wegschicken. Dann vermehrt die Base64-Kodierung den Datenumfang noch mal ein ganzes Stueck - und mit in Deutschland ueblichen ADSL-Anschluessen geht der Upload noch mal um einiges langsamer als der Download.
              Das duerfte schon bei "kleineren" Dateigroessen schnell zur Zumutung werden.
              Ganz abgesehen davon, dass vielleicht auch noch der ein oder andere Browser Probleme macht, wenn man so viel Inhalt im value-Attribut eines Formularfeldes unterbringt.

              MfG ChrisB

              --
              „This is the author's opinion, not necessarily that of Starbucks.“
              1. »» Das ist natürlich ein naheliegender Ansatz. Leider geht er bei mir nicht. Das Verschicken der Datei an einen zweiten Server muss beim Benutzer ein Fenster aufklappen, in dem er sich typischerweise erst einmal anmelden und dann die weiteren Schritte bestätigen muss.

                Bei wem muss sich der Benutzer anmelden, bei Server 1 oder Server 2?

                Zunächst natürlich bei Server 1, damit er dort überhaupt arbeiten kann. Wenn er den genannten Versendevorgang auslöst, muss er sich auch bei Server 2 anmelden.

                »» Daher war meine Idee, vom ersten Server aus eine Antwort an den Benutzer zu schicken, in dem die Datei Base64-kodiert in einem versteckten Formular enthalten ist und als ACTION eine URL auf dem zweiten Server angegeben ist. Das Submit zu diesem Formular wird automatisch ausgelöst, die Daten werden zum zweiten Server übertragen, dieser baut seine Antwortseite, so wie gewünscht, beim Benutzer auf. - Nur: Wie baut man dieses versteckte Formular auf?

                Na mit HTML ...
                Hidden Field, kodierte und ggf. entsprechend maskierte Daten ins value-Attribut reinschreiben.

                Dann hat doch der Base64-Text gar nicht den richtigen MIME-Typ, sondern ist einfach nur Text. Ich hatte an eine korrekt aufgebaute Multipart-Message gedacht. Die bekomme ich ja mit einem Upload-Formular (eins mit <input type=file>-Element. So etwas bräuchte ich, nur eben mit implizit enthaltener Datei.

                Sauber ließe sich das mit einem <object>-Element mit Inline-Daten im data-Attribut lösen. So etwas darf man laut W3C auch in Formulare packen. Nur kann das meines Wissens kaum ein Browser. Und damit nützt es mir nichts, ich kann keine Voraussetzung an die Browser unserer Nutzer stellen.

                Gibt es nicht mit vorhandenen Mitteln eine Möglichkeit, ein Formular mit eingebetteter Datei aufzubauen, die zu einer korrekt aufgebauten Multipart-Message führt?

                1. Moin!

                  Gibt es nicht mit vorhandenen Mitteln eine Möglichkeit, ein Formular mit eingebetteter Datei aufzubauen, die zu einer korrekt aufgebauten Multipart-Message führt?

                  Nein, denn deine Möglichkeiten sind nun mal beschränkt.

                  Erstens: Du musst zwingend einen POST-Request versenden. Damit reduzieren sich deine Möglichkeiten auf alles, was im Client oder auf dem Server 1 POST-Requests auf Server 2 machen kann.

                  Zweitens: Du willst den Server 1 beim Request weggelassen wissen. Also bleiben dir noch sämtliche Methoden, die im Client entsprechende Möglichkeiten bieten.

                  Die aktuell bekannten Möglichkeiten clientseitiger POST-Request-Erzeugung bestehen aus:

                  1. Formulare mit method=POST.
                  2. AJAX.
                  3. Flash.

                  Die Möglichkeit 1 wurde hier bereits ausführlich als unmöglich deklariert. Um mit einem Formular Dateien versenden zu können, ist es erforderlich, dass diese Datei sich auf dem Client befindet und in einem manuellen, nicht vorwählbaren Prozess vom Benutzer ausgewählt wird. Die Datei befindet sich aber nicht auf dem Client, sondern müsste zuvor manuell heruntergeladen werden.

                  Die Methode der server1-seitigen passenden Einbettung der Datei in z.B. BASE64 erfordert Anpassungen auf dem Server 2, damit er dieses Format versteht. Ich gehe mal davon aus, dass das nicht möglich ist.

                  Die Methode, das Formular ohne Datei an Server 1 zu senden, gemeinsam mit den Anmeldedaten für Server 2, um dann Server 1 den POST inklusive Datei machen zu lassen, wurde von dir auch verworfen.

                  Wenn wir Flash mal außenvor lassen, bleibt AJAX. AJAX erlaubt es in gewissen Grenzen, den Request zu beeinflussen.

                  Mit Javascript und somit bei AJAX kann man nicht auf das lokale Dateisystem des Clients zugreifen. Diese Antwort erhält man global in allen Foren, und sie ist korrekt. Diese Aufgabe hier erfordert das aber ja gerade nicht, denn die Datei liegt ja auf Server 1, und Server 1 ist wunderbar für jedes Javascript erreichbar, welches in einer HTML-Seite eingebettet ist, die ebenfalls von Server 1 ausgeliefert wird.

                  Es ist also denkbar, mit AJAX einen Multipart-Request zusammenzubauen. Folgende Antwort zeigt dazu einen Ansatz: http://bytes.com/groups/javascript/165254-ajax-prototype-js-multipart-form-data. Es wäre also denkbar, von Server 1 ein Formular mit einem versteckten riesigen Formularfeld (plus ein paar Metainformationen z.B. in anderen Feldern) abzurufen, und diese Dateidaten dann im AJAX-Request wieder zurückzuspielen.

                  Die Sache hat nur einen Haken: AJAX-Requests funktionieren nur im Rahmen der Same-Origin-Policy. DU kannst also nur dann einen frei formulierten POST-Request verwenden, wenn Server 1 das Ziel ist. Auf Server 2 hast du mit AJAX nur dann Zugriff, wenn AJAX-absendende Formularseite von Server 2 geladen wurde. Dann könnte man die Datei sogar per <script>-Einbindung von Server 1 verfügbar machen, und es würde funktionieren. Aber da ich ahne, dass du Server 2 nicht beeinflussen kannst, ist dir diese Möglichkeit verschlossen.

                  Und im Übrigen: Diese ganze Konstruktion ist so dermaßen manipulationsanfällig, dass man sie eigentlich absolut vermeiden will.

                  Und aufgrund der Same-Origin-Policy für AJAX-Requests dürfte es verständlich sein, warum derartige Konstruktionen nicht so wahnsinnig häufig nachgefragt werden: Wenn Quell- und Zielserver identisch sein müssen, lohnt es sich einfach nicht, die Datei zweimal über die Leitung zu schieben - von der Manipulationsgefahr auf dem Client mal ganz abgesehen.

                  - Sven Rautenberg

                  1. Moin Sven,

                    danke für deine ausführliche und sachkundige Erklärung. Sie war sehr lehr- und hilfreich, auch wenn mein Wunschtraum damit nicht Wahrheit wird :-)

                    Ich denke, ich werde einen dieser beiden Wege versuchen zu öffnen. Dazu muss ich allerdings mit dem zuständigen Fachmann auf Server-2-Seite verhandeln:

                    Die Methode der server1-seitigen passenden Einbettung der Datei in z.B. BASE64 erfordert Anpassungen auf dem Server 2, damit er dieses Format versteht. Ich gehe mal davon aus, dass das nicht möglich ist.

                    Die Methode, das Formular ohne Datei an Server 1 zu senden, gemeinsam mit den Anmeldedaten für Server 2, um dann Server 1 den POST inklusive Datei machen zu lassen, wurde von dir auch verworfen.

                    Gibt es denn eine standardisierte Möglichkeit, die Anmeldedaten mit einem Request gleich mitzuliefern?

                    Franz

                    1. Moin!

                      »» Die Methode, das Formular ohne Datei an Server 1 zu senden, gemeinsam mit den Anmeldedaten für Server 2, um dann Server 1 den POST inklusive Datei machen zu lassen, wurde von dir auch verworfen.

                      Gibt es denn eine standardisierte Möglichkeit, die Anmeldedaten mit einem Request gleich mitzuliefern?

                      Nein. Wenn HTTP-Authentifizierung notwendig ist, geht es in aktuellen Browsern sowieso nicht (ältere Modelle ließen sich mal darauf ein, dass die Anmeldedaten in der HTTP-URL mitgeliefert wurden wie bei FTP möglich. Dummerweise ist diese Methode für HTTP nicht erlaubt und hat auch diverse Probleme und unerwünschte Nebeneffekte verursacht, deshalb hat man sich darauf besonnen, den Standard nicht zu erweitern, sondern die Browser zu beschränken).

                      Ansonsten gibt es nur noch die Übermittlung der Anmeldedaten in einem HTML-Formular - und das ist grundsätzlich ja machbar.

                      Allerdings hängt es wiederum vom Authentifizierungsmechanismus ab, was der Server 2 denn tatsächlich erfordert. Eventuell setzt er zwingend zuerst ein Cookie, eröffnet eine Session, und erlaubt gar keinen direkten POST-Request.

                      - Sven Rautenberg

                      1. Hallo,

                        Nein. Wenn HTTP-Authentifizierung notwendig ist, geht es in aktuellen Browsern sowieso nicht (ältere Modelle ließen sich mal darauf ein, dass die Anmeldedaten in der HTTP-URL mitgeliefert wurden wie bei FTP möglich

                        Doch:  Opera 9/10, FF3 (2 hab ich leider nicht), Chrome1, ... können das alle - so logge ich mich hier ein (Verknüpfung aufm desktop)

                        mfg, Flo

                        --
                        sh:) fo:| ch:? rl:( br:^ n4:| ie:{ mo:| va:} de:> zu:} fl:{ ss:) ls:< js:|
                        1. Moin!

                          »» Nein. Wenn HTTP-Authentifizierung notwendig ist, geht es in aktuellen Browsern sowieso nicht (ältere Modelle ließen sich mal darauf ein, dass die Anmeldedaten in der HTTP-URL mitgeliefert wurden wie bei FTP möglich
                          Doch:  Opera 9/10, FF3 (2 hab ich leider nicht), Chrome1, ... können das alle - so logge ich mich hier ein (Verknüpfung aufm desktop)

                          Da kommt aber zumindest eine Meldung, ob man denn wirklich mit Anmeldename und Passwort die neue Seite aufrufen will.

                          Und im IE geht es halt nicht. Das ist das Ausschlusskriterium.

                          Zweites Ausschlußkriterium: Wenn man die Anmeldedaten in die URL packen will, muss man sie in einem Formularfeld abfragen.

                          Heißt: Server 1 liefert ein Formular aus, welches auf Server 2 gehen soll, und fragt nach den Anmeldedaten für Server 2. Um dann mit viel Javascript die Login-URL zusammenzubasteln (mit AJAX könnte man es evtl. sogar standardkonform in den HTTP-Header einbinden, wenn die Same-Origin-Policy nicht wäre).

                          Wenn das so läuft, kann man sich das Leben mit dem Dateiversand auch einfacher machen, und das Formular mit den Anmeldedaten zum Server 1 schicken, damit der den Upload übernimmt. Damit würde vieles einfacher, aber das ist ja gerade nicht gewünscht.

                          - Sven Rautenberg

    2. hi $name,

      Ich hätte noch dazusagen sollen, dass die zu verschickende Datei auf dem Server liegt. Es soll also nicht, wie bei

      <input type="FILE" ...>

      eine Datei vom Client verschickt werden.

      das verarbeitende script muss doch die datei verschicken, damit es weiß welche datei zu verschicken ist kannst du den DATEINAMEN per hidden filed übergeben.
      gruss
      shadow

      --
      Vor dem Parser und auf hoher See sind wir allein in Gottes Hand
      1. das verarbeitende script muss doch die datei verschicken, damit es weiß welche datei zu verschicken ist kannst du den DATEINAMEN per hidden filed übergeben.

        Das verarbeitende Skript kennt den Dateinamen und hat Zugriff auf die Datei, sie liegt auf dem Server. Es muss die Datei selbst verschicken.

        1. hi $name,

          Das verarbeitende Skript kennt den Dateinamen und hat Zugriff auf die Datei, sie liegt auf dem Server. Es muss die Datei selbst verschicken.

          ja dann gibt es ja auch kein problem....

          gruss
          shadow

          --
          Vor dem Parser und auf hoher See sind wir allein in Gottes Hand
    3. Ich hätte noch dazusagen sollen, dass die zu verschickende Datei auf dem Server liegt. Es soll also nicht, wie bei

      <input type="FILE" ...>

      eine Datei vom Client verschickt werden.

      Dann reicht wohl ein copy-Befehl.

      Hotte

      --
      Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.