Hans: PHP-FTP upload bei großen Dateien

Hallo,

Ich habe ein kleines PHP-Uploadscript, welches mit den standartisierten Uploadfunktionen Dateien auf meinen Server übertragen kann.

nach dem schema: $upload = ftp_put($conn_id, "$destination_file", "$source_file", FTP_BINARY);

funktioniert eigentlich auch, nur bei größeren Dateien
bricht der server wegen zeitüberschreitung ab.

Kann ich da irgendwas umbauen, so dass es funktioniert?

Danke!
Hans

  1. Eine Zeitüberschreitung hat doch aber mit dem php-Skript nix zu tun. Anscheinend ist deine Upload-Performance (seitens Provider, DSL oder ServerHost) schlecht. Das solltest du evtl. mal mit Speedmeter.de überprüfen... mfg

    1. Moin erik,

      »» Eine Zeitüberschreitung hat doch aber mit dem php-Skript nix zu tun. Anscheinend ist deine Upload-Performance (seitens Provider, DSL

      u.U. doch. Es kann einen Script- oder CGI Timeout geben.
      Das könnte weiterhelfen set_time_limit(0); und oder den CGI Timeout hoch setzen.

      regds
      Mike©

      --
      Freunde kommen und gehen. Feinde sammeln sich an.
      1. u.U. doch. Es kann einen Script- oder CGI Timeout geben.
        Das könnte weiterhelfen set_time_limit(0); und oder den CGI Timeout hoch setzen.

        Na dann hab ich wenigstens wieder was dazugelernt...

  2. Moin!

    Kann ich da irgendwas umbauen, so dass es funktioniert?

    Wenn Dein Hoster das zulässt kannst Du die Werte höhersetzen. Das geht zum einen mit ini_set(variable,wert), zum anderen durch Einstellen der Wert-Value-Paare aus der PHP.ini in die .htaccess - Datei.

    MFFG (Mit freundlich- friedfertigem Grinsen)

    fastix®

    --
    Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
  3. Hallo,

    danke für die Antworten erstmal...
    wäre es nicht möglich, den upload sozusagen aufzuspalten und z.B. je 100 kb direkt nacheinander upzuloaden und nicht 1mb auf einmal?
    die einzelnen parts könnten so durch eine automatische weiterleitung
    geladen werden, so dass die zeit nicht überschritten wird.
    Gibt es eine FTP-Spaltungsfkt. bei PHP?
    Danke!

    1. Moin!

      Gibt es eine FTP-Spaltungsfkt. bei PHP?

      Du kannst Dateien nach Belieben splitten. Das geht mit einer ganzen Anzahl von 'text'-Funktionen.

      Es gibt aber eine weitere Möglichkeit: system() - Hier die Beschreibung wie in etwas es auf einem UNIX/Linux-System aussehen könnte:

      system("shellsript.sh 1> logfile.txt 2> errors.txt &");

      ... bewirkt, dass das Shellskript von der aktuellen Shell "abgehangen" im Hintergrund ausgeführt wird. Die Rückgaben werden nach logfile geschrieben und stehen so einer künftigen Verwendung zur Verfügung. Zum Bleistift könnte man eine Auswertungs-Seite aller paar Sekunden neu laden und warten, bis in der letzten Zeile vom logfile.txt 'EOT' steht oder Fehler in errors.txt auftauchen.

      Die Datei errors.txt sollte beim Laden (so sie existiert: keine Fehler-> keine Datei) also mit ausgewertet werden.

      shellscript sh: (Mit Zeilenumbrüchen, aber ohne weitere Leerzeilen am Beginn):
      #! /bin/sh
      cut ftpskript | ftp server.tld
      echo -ne '\nEOT'

      fertig.

      ftpskript (Mit Zeilenumbrüchen, aber ohne weitere Leerzeilen am Beginn):
      DeinPasswordAufDemServer
      cd DeinUploadDir
      put Datei
      bye

      Voraussetzung ist, dass ein FTP-Client existiert und dass Du diesen ausführen darfst.

      MFFG (Mit freundlich- friedfertigem Grinsen)

      fastix®

      --
      Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
      1. Hallo,

        danke, aber ich darf keinen FTP-Client ausführen.
        Ich hab da noch ne Idee: Wie wäre es, wen ich eine Datei öffne, ichren "Code" Zeile für Zeile, bzw. z.B. 10 Zeilen auf einmal auslese, und dann auf dem Server in einer Datei speichere?
        Müsste doch gehen?
        Bzw, muss man da aufpassen ob die Datei binär etc. übertragen werden muss?

        Danke!
        Hans

        1. Moin!

          danke, aber ich darf keinen FTP-Client ausführen.

          Geht es auch anders? Zum Bleistift mit scp? Das Verfahren wäre prinzipiell gleich.

          Ich hab da noch ne Idee: Wie wäre es, wen ich eine Datei öffne, ichren "Code" Zeile für Zeile, bzw. z.B. 10 Zeilen auf einmal auslese, und dann auf dem Server in einer Datei speichere?
          Müsste doch gehen?

          Zeilenweise? Wielange soll das denn dauern?

          Bzw, muss man da aufpassen ob die Datei binär etc. übertragen werden muss?

          -> http://de3.php.net/manual/de/ref.ftp.php

          MFFG (Mit freundlich- friedfertigem Grinsen)

          fastix®

          --
          Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
          1. hallo,

            muss mal gucken wegen scp, weiß nicht, ob der Hoster das erlaubt.
            Man könnte doch anstatt zeilenweisen auch byteweise vorgehen, oder?
            z.B. immer 100kb nacheinander...

            MfG Hans

      2. echo $begrüßung;

        system("shellsript.sh 1> logfile.txt 2> errors.txt &");

        ... bewirkt, dass das Shellskript von der aktuellen Shell "abgehangen" im Hintergrund ausgeführt

        Hast du mal probiert, ob das auch funktioniert/stimmt?

        echo "$verabschiedung $name";

        1. Moin!

          Hast du mal probiert, ob das auch funktioniert/stimmt?

          Extra für Dich habe ich das jetzt gemacht. Ich nehme richtig an, Du hast es nicht hinbekommen?

          system("shellsript.sh 1> logfile.txt 2> errors.txt &");

          Tut es prinzipiell. Voraussetzungen: shellscript.sh ist auführbar und in das Verzeichnis in $PATH.

          Sonst meinetwegen:
          system("./shellsript.sh 1> logfile.txt 2> errors.txt &");

          Wie man an einer Unix-Shell Skripte aufruft sollte jedem klar sein, der es tut. Darüber hinaus ist auf unterschiedlichen Unix/Linux-Systemen für normale Benutzer das aktuelle Verzeichnis (".") im Pfad oder nicht. Warum es das für den root hoffentlich nicht ist, erkläre ich Dir gerne für viel Geld.

          Test unter http://fastix.dyndns.org/shell/
          (Absichtlich kein Link! Quelltexte an Ort und Stelle.)

          Kommen wir zum Skript und zum ftp.skript:

          shellscript sh: (Mit Zeilenumbrüchen, aber ohne weitere Leerzeilen am Beginn):
          #! /bin/sh
          cut ftpskript | ftp ftp://user:passwort@server.tld

          gleichwertige Alternative:

          ftp ftp://user:passwort@server.tld < ftpskript

          echo -ne '\nEOT'

          fertig.

          ftpskript (Mit Zeilenumbrüchen, aber ohne weitere Leerzeilen am Beginn):
          cd DeinUploadDir
          put Datei
          bye

          Einige FTP-Clients lassen sich scheinbar nicht das Passwort von hinten durch das Rohr reinblasen- offenbar um das Passwort nicht in der Prozessliste zu kompromittieren- das wird es aber dennoch, wenn man es wie beschrieben aufruft. Mit dem Rest geht es wohl. Hab es grade getestet. Das sind aber jetzt nur marginale Syntax-Fehlerchen. Wenn prinzipilelle Lösungen gesucht werden, dann sollte auch berücksichtigt werden, das nicht wegen jeder kleinen Lösung gleich ein Riesen-Versuchsaufbau gemacht werden kann und das eventuelle kleine Problemchen mit der Syntax selbst zu erkennen sind- oder?

          Warum ich im Gegensatz zu manch über Windows und Webserver gar nicht erst nachdenke sollte Dir klar sein. Für diese Art von Webserver gibts doch extra den einzigartigen "24/7-Reebotservice mit 15 Minuten Reaktionszeit".

          MFFG (Mit freundlich- friedfertigem Grinsen)

          fastix®

          --
          Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
          1. Moin!

            Test unter http://fastix.dyndns.org/shell/
            (Absichtlich kein Link! Quelltexte an Ort und Stelle.)

            Test unter http://fastix.dyndns.org/test/shell/

            MFFG (Mit freundlich- friedfertigem Grinsen)

            fastix®

            --
            Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
          2. echo $begrüßung;

            Hast du mal probiert, ob das auch funktioniert/stimmt?

            Extra für Dich habe ich das jetzt gemacht. Ich nehme richtig an, Du hast es nicht hinbekommen?

            Ja, ich habe es nicht hinbekommen. Jedenfalls nicht so, dass das Shellscript sich von PHP abgekoppelt hat. Es lief zwar los, jedoch blieb dabei auch das PHP-Script stehen und wartete auf die Beendigung des Prozesses. Ein »von der aktuellen Shell "abgehangen" im Hintergrund ausgeführt« konnte ich nicht erkennen.

            Test unter http://fastix.dyndns.org/shell/

            Das von dir verwendete Shellscript ist ja sofort wieder beendet. Damit sehe ich es als ungeeignet an, eine Ausführung im Hintergrund zu testen bzw. nachzuweisen.

            Mein test.sh sah so aus:

            #!/bin/bash
            cd /tmp
            while true
            do
              date >> test.dat
              sleep 2s
            done

            Der Aufruf erfolgte überein:

            echo system('./test.sh 2> /tmp/error &');

            Mit einem

            tail -f /tmp/test.dat

            sah ich, dass es vor sich hin lief. Erst nach der gewaltsamen Beendigung des Endlosschleifen-Scripts mittels

            killall test.sh

            lief dann auch das PHP-Script weiter.

            echo "$verabschiedung $name";

            1. Moin!

              fastix@trainer:/www/test/shell2> php < index.php
              Content-type: text/html
              X-Powered-By: PHP/4.3.3

              <p>starte</p><p>fertig</p>fastix@trainer:/www/test/shell2>
              fastix@trainer:/www/test/shell2> ps ax | grep test
              10922 pts/17   S      0:00 /bin/sh ./test.sh
              10968 pts/17   R      0:00 grep test
              fastix@trainer:/www/test/shell2>

              index.php:
              <?php
              echo "<p>starte</p>";
              $dummy=./test.sh >logfile 2>errors &;

              system('./test.sh >logfile 2>errors &');

              tut auch...

              echo "<p>fertig</p>";
              echo $dummy;
              ?>

              test.sh
              #!/bin/sh
              while true
              do
                date
                sleep 1
              done

              Der Unterschied ist lediglich, dass stdout sofort umgeleitet wird. Dann wartet Dein Skript nicht auf irgendwas...

              MFFG (Mit freundlich- friedfertigem Grinsen)

              fastix®

              --
              Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
              1. Moin!

                Der Unterschied ist lediglich, dass stdout sofort umgeleitet wird. Dann wartet Dein Skript nicht auf irgendwas...

                Ganz genau genommen besteht der Unterschied darin, dass Dein Skript brav auf die Beendigung der Rückgaben gewartet hat. Leitest Du stdout um, dann bekommt es sofort ein EOT (End Of Transmission) gesendet und rackert weiter, während der angestoßene Prozess im Hintergrund weiterläuft.

                Gut, dass Du mir mal Anlass gabst, die Theorie praktisch zu betätigen: Denn: Soweit zum Thema "Mein Provider bietet mir keine Chronjobs" :)))

                Natürlich muss man immer mal überprüfen, ob der Job noch läuft. Das geht aber mit

                if (ps ax| grep /verz/verz/plapla.sh | wc-l < 2) {
                    $dummy=/verz/verz/plapla.sh > plapla.log 2> plapla.errors
                }

                Jetzt muss plapla nur noch gut genug programmiert sein um nicht zuviel Systemlast zu fressen und Prozesse in geeigneten Abständen zu starten. 'sleep' und 'date' liefern echt praktische Dinge...

                (Den else- Zweig oder wie man zuviele solche Prozesse stoppt liefere ich gegen viel Bargeld :))))

                MFFG (Mit freundlich- friedfertigem Grinsen)

                fastix®

                --
                Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development
                1. echo $begrüßung;

                  Ganz genau genommen besteht der Unterschied darin, dass Dein Skript brav auf die Beendigung der Rückgaben gewartet hat. Leitest Du stdout um, dann bekommt es sofort ein EOT (End Of Transmission) gesendet und rackert weiter, während der angestoßene Prozess im Hintergrund weiterläuft.

                  Gut, eine nicht beachtete stdout-Umleitung wird wohl auch meinen Test vor einiger Zeit mit einem negativen Ergebnis beendet haben. Deswegen meine skeptische Nachfrage.

                  Dieses Problem scheint auch nicht mehr zu existieren (4.3.11 und 5.0.4). Ein mit set_time_limit(5) gestartetes und 99.x% Prozessorlast erzeugendes while true;do true;done wurde bei mir jedenfalls nicht in absehbarer Zeit beendet.

                  echo "$verabschiedung $name";

        2. Moin!

          ... bewirkt, dass das Shellskript von der aktuellen Shell "abgehangen" im Hintergrund ausgeführt

          Hast du mal probiert, ob das auch funktioniert/stimmt?

          Falls Du das "abhängen" meinst:

          fastix@trainer:~> firefox &
          [1] 9685
          fastix@trainer:~>

          ... firefox startet
          ... ich schließe die Konsole
          ... firefox lebt noch

          Das gleiche passiert wenn ich mich auf einer echten Konsole einlogge und dann:

          fastix@trainer:~> export DISPLAY=localhost:0
          fastix@trainer:~> firefox &
          [1] 9697
          fastix@trainer:~> exit
          ... Damit ist die login-Shell beendet

          Mit [ALT]+[F7] zurück: Er lebt noch.

          Merke: Mit einem angehangenem '&' hängt man Prozesse vom aktuellen Prozess (z.B. shell) ab. Der Tot der shell oder des Elternprozesses reisst den Kindprozess nicht mehr in den ekletrektischen Tot.

          Ich habe das _nicht_ _einmal sondern etliche Male zwar nicht _probiert_ aber _angewendet_.

          MFFG (Mit freundlich- friedfertigem Grinsen)

          fastix®

          --
          Als Freiberufler bin ich immer auf der Suche nach Aufträgen: Schulungen, Seminare, Training, Development