DanielE: Progessbar beim Downlaoden von Dateien (Ajax)

Hallo zusammen,

hier eine Kurzfassung: Ein PHP-Skript läuft im Webserver relativ lange, da es mit set_time_limit() verlängert wird. Im selben Moment soll ein weiteres Skript aufgerufen werden. Da scheint allerdings vom anderen Skript blockiert zu werden, bis es fertig ist.
Und jetzt im Detail. Ich habe folgende Anforderung umzusetzen. Auf einem Server befinden sich Dateien. Benutzer können mit einem Webfrontend diese Dateien downloaden. Ein Client hat ebenfalls diese Software (ein kleines Webinterface) installiert und bei Bedarf kann der Client mit dem Server Daten austauschen. Dazu lädt das Skript die Dateien vom Server bzw. uploaded sie. Da die Dateien relativ groß sind (ca. 30MB) dauert das ganze natürlich eine Zeit lang. Die Daten tausche ich per FTP mittels PHP-FTP-Funktionen aus. Damit das Skript nicht abbricht nutze ich set_time_limit(). Jetzt zum eigentlichen Problem. Ich wollte eine Progessbar anzeigen, wieviel der Datei schon gedownloaded ist. Also habe ich folgendes machen wollen: Ich rufe per http_request ein Skript auf, welches die Datei lädt. Das Skript läuft natürlich relativ lange. Damit ich nun sehen kann, wieviel der Datei schon gedownloaded ist, macht ein anderer Http-Request im 2 Sek. Rhythmus eine Abfrage, wie groß die gedownloadete Datei bereits ist. Daraufhin hätte ich dann die Anzeige in einer Progressbar per JavaScript angezeigt. Der zweite HTTP-Request funktioniert allerdings nicht, denn die PHP-Seite, die hier aufgerufen werden soll, ist solange nicht aufrufbar, bis die Datei gedownloaded ist. Scheinbar blockt das eine Skript das andere Skript. Hat jemand eine Idee, was man hier machen kann?!?

Gruß und schon herzlichen Dank für die Antworten!

Daniel

  1. echo $begrüßung;

    Ein PHP-Skript läuft im Webserver relativ lange, da es mit set_time_limit() verlängert wird. Im selben Moment soll ein weiteres Skript aufgerufen werden. Da scheint allerdings vom anderen Skript blockiert zu werden, bis es fertig ist.

    Das kann dann der Fall sein, wenn der Webserver so ausgelastet ist, dass er den zweiten Request gleich gar nicht berücksichtigen kann. Oder aber das zweite Script wird zwar gestartet, wartet aber freiwillig oder gezwungen auf die Freigabe der vom ersten Script belegten Ressource. Ebenfalls möglich ist, dass der Client sich blockiert hat weil er auf die Antwort des ersten Scripts wartet. Es ist eine gängige Einstellung in den Clients, die Anzahl der parallelen Requests zum gleichen Server einzuschränken.

    Auf einem Server befinden sich Dateien. Benutzer können mit einem Webfrontend diese Dateien downloaden. Ein Client hat ebenfalls diese Software (ein kleines Webinterface) installiert und bei Bedarf kann der Client mit dem Server Daten austauschen.

    Was genau muss man sich unter "kleines Webinterface installiert" vorstellen? Wenn es mehr ist als in einem herkömmlichen Browser angezeigtes HTML (evtl. gewürzt mit etwas Javascript) warum kann es dann nicht auf Ereignisse wie "wieder ein Stück Datei übertragen" reagieren und eine Fortschrittsanzeige bedienen?

    Ich rufe per http_request ein Skript auf, welches die Datei lädt. Das Skript läuft natürlich relativ lange. Damit ich nun sehen kann, wieviel der Datei schon gedownloaded ist, macht ein anderer Http-Request im 2 Sek. Rhythmus eine Abfrage, wie groß die gedownloadete Datei bereits ist.

    Ein HTTP-Prozess läuft auf dem Server normalerweise in einer gekapselten Umgebung ab und hat keinen Zugriff auf andere parallel laufende Requests. Möchte er Informationen an andere Prozesse zur Verfügung stellen müsste er das über einen gemeinsam zugreifbaren Speicherbereich (im RAM oder Dateisystem) tun.

    Wenn du allerdings den Server befragst, wieviel er schon auf die Reise geschickt hat, muss das nicht unbedingt mit dem übereinstimmen, was schon beim Client gelandet ist. Unterwegs gelegene Zwischenspeicher könnten eine Differenz beherbergen.

    Daraufhin hätte ich dann die Anzeige in einer Progressbar per JavaScript angezeigt. Der zweite HTTP-Request funktioniert allerdings nicht, denn die PHP-Seite, die hier aufgerufen werden soll, ist solange nicht aufrufbar, bis die Datei gedownloaded ist. Scheinbar blockt das eine Skript das andere Skript. Hat jemand eine Idee, was man hier machen kann?!?

    Nicht ohne Einsicht in die derzeitige Implementation. Wobei ich diesen Weg zugunsten der oben angedeuteten Möglichkeiten nicht weiter verfolgen würde.

    echo "$verabschiedung $name";

    1. Aloha!! Und danke für die Antwort.

      Das kann dann der Fall sein, wenn der Webserver so ausgelastet ist, dass er den zweiten Request gleich gar nicht berücksichtigen kann. Oder aber das zweite Script wird zwar gestartet, wartet aber freiwillig oder gezwungen auf die Freigabe der vom ersten Script belegten Ressource. Ebenfalls möglich ist, dass der Client sich blockiert hat weil er auf die Antwort des ersten Scripts wartet. Es ist eine gängige Einstellung in den Clients, die Anzahl der parallelen Requests zum gleichen Server einzuschränken.

      Das wird wahrscheinlich der Fall sein, wobei es ja eigentlich nur eine Übertragung einer Datei per FTP ist. Das sollte eigentlich keine anderen PHP-Prozesse blokieren? Ausgelastet ist das System, wenn man sich die Prozessliste anschaut, nicht. Mit den Client halte ich eher für unwahrscheinlich, da andere Test von mir gezeigt haben, dass er die verarbeiten kann, nur der Webserver reicht nicht schnell genug Infos weiter.

      Was genau muss man sich unter "kleines Webinterface installiert" vorstellen? Wenn es mehr ist als in einem herkömmlichen Browser angezeigtes HTML (evtl. gewürzt mit etwas Javascript) warum kann es dann nicht auf Ereignisse wie "wieder ein Stück Datei übertragen" reagieren und eine Fortschrittsanzeige bedienen?

      Hier noch einmal ein paar detailiertere Infos zur Technik, die ich verwenden möchte bzw., wie ich mir das vorstelle. Also ich lade eine Datei per FTP mittels PHP von einem Server runter. D.h. das PHP auf dem Server, welches ich per Browser aufrufe, läuft etwa 3-4 min, bis die Datei fertig geladen hat. Das Problem ist, dass ein Benutzer, der davor sitzt, natürlich ungeduldig wird, da das ganze so lange dauert. Also war die Idee folgende:
      Ich öffne per JavaScript und Dojo ein Dialogfenster. Das deaktiviert den Hintergrund der HTML-Seite. Nachdem das Fenster geöffnet ist, sende ich einen Ajax-HTTP-Request an den Webserver und rufe die Seite auf, die die Datei downloaded. Dieser Ajax-Http-Request dauert natürlich relativ lange (also die 3-4 min, die er zum download benötigt). Parallel dazu mache ich mit setInterval in regelmäßigen Abständen einen zweiten Ajax-HTTP-Request. Dieser soll einen Service auf dem Webserver ansprechen, welcher die Dateigröße einer Datei anzeigt, die gerade gedownlaoded wird. Deshalb brauche ich auch nicht auf den anderen Prozess zu warten, ich greife ganz einfach auf die Datei im Filesystem zu und die wird immer größer. Ist zwar nicht 100%ig die richtige Größe der Datei, aber so wichtig ist das auch nicht. Es stimmt halt so grob. Wenn jetzt der zweite Ajax-HTTP-Request antwortet. Habe ich die ungefähre Größe der Datei also, wie groß ist die Datei etwa. Daraufhin könnte man dann ausrechnen, wie groß ein Balken in einer Progessbar sein soll. Wenn der erste Ajax-HTTP-Request fertig ist, dann ist der Download beendet und ich kann den Javascript-Dialog schließen und clearInterval aufrufen, damit er nicht immer die Dateigröße pollt.

      Der zweite Ajax-HTTP-Request, um die Dateigröße zu bekommen funktioniert allerdings nicht, wie der Apache bzw. PHP blockt und erst wieder antwortet, wenn die Datei gedownloaded ist... dumm oder! Ich bin mir nicht sicher, ob ich das vorher so verständlich formuliert habe. Hoffentlich ist es jetzt besser.

      Ich habe übrigens eine andere Implementierung hinbekommen, die nicht ganz so schön ist. Also ich habe folgendes gemacht: Die Progessbar bewegt sich einfach nur hin und her. Ich frage also nicht ständig die Dateigröße ab und wenn die Datei gedownloaded ist - das weiß ich ja, wenn der Ajax-HTTP-Request antwortet, dann schließe ich den Javascript-Dialog. Funktioniert zwar und ist schon besser als einfach  nur das Skript laufen zu lassen und den Benutzer warten zu lassen, aber besser ist natürlich eine Anzeige, die genauer ist.

      Gruß und nochmals Danke

      Daniel

      1. echo $begrüßung;

        Hier noch einmal ein paar detailiertere Infos zur Technik, die ich verwenden möchte bzw., wie ich mir das vorstelle. Also ich lade eine Datei per FTP mittels PHP von einem Server runter. D.h. das PHP auf dem Server, welches ich per Browser aufrufe, läuft etwa 3-4 min, bis die Datei fertig geladen hat. Das Problem ist, dass ein Benutzer, der davor sitzt, natürlich ungeduldig wird, da das ganze so lange dauert. Also war die Idee folgende:

        Achso ... Du verwendest dazu wahrscheinlich entweder Dateifunktionen mit ftp://-Vorspann oder PHPs FTP-Funktionen. Im letzteren Fall könntest du es ohne zweites Script mit der nicht blockierenden Variante von ftp_(f)get() namens ftp_nb_(f)get() versuchen (Userkommentar beachten). flush() könnte auch interessant sein, damit der Apache angeregt wird, die Ausgabe sofort an den Client zu senden.

        Auf dem Client kannst du dir ja was einfallen lassen. Das Beispiel mit dem echo '.'; ist recht trivial. Vielleicht kann man was mit den ankommenden Punkten oder HTML-Schnipseln und etwas Javascript was schönes zaubern ...

        echo "$verabschiedung $name";

        1. Hi Ho!!!

          Achso ... Du verwendest dazu wahrscheinlich entweder Dateifunktionen mit ftp://-Vorspann oder PHPs FTP-Funktionen. Im letzteren Fall könntest du es ohne zweites Script mit der nicht blockierenden Variante von ftp_(f)get() namens ftp_nb_(f)get() versuchen (Userkommentar beachten). flush() könnte auch interessant sein, damit der Apache angeregt wird, die Ausgabe sofort an den Client zu senden.

          Also der Client hat ebenfalls einen Apache installiert. Deshalb brauche ich nur die Dateifunktionen, die auf das lokale Dateisystem liegen, auf dem Client-Server (klinkt irgendwie komisch) aufrufen.

          Auf dem Client kannst du dir ja was einfallen lassen. Das Beispiel mit dem echo '.'; ist recht trivial. Vielleicht kann man was mit den ankommenden Punkten oder HTML-Schnipseln und etwas Javascript was schönes zaubern ...

          Hmm, cooole Idee! Funktioniert auch gut, aber dummerweise interpretiert der Brwoser das JavaScript erst, wenn es vollständig geladen ist, oder?!?

          Eine andere Idee von mir wäre gewesen, dass ich wiederum per Ajax das Skript aufrufe und das mir, wenn 1 Prozent mehr gedownloaded ist, einen weiteren Punkt liefert. Dummerweise kann ich erst auf responceText zugreifen, wenn die Seite vollständig geladen ist. Und das wäre erst der Fall, wenn die Datei per FTP vollständig gedownload ist.

          Gruß und danke

          Daniel

      2. Hi DanielE,

        Hier noch einmal ein paar detailiertere Infos zur Technik, die ich verwenden möchte bzw., wie ich mir das vorstelle. Also ich lade eine Datei per FTP mittels PHP von einem Server runter. D.h. das PHP auf dem Server, welches ich per Browser aufrufe, läuft etwa 3-4 min, bis die Datei fertig geladen hat. Das Problem ist, dass ein Benutzer, der davor sitzt, natürlich ungeduldig wird, da das ganze so lange dauert.

        Hm... Wie dedlfix schon erwähnt hat, stößt du hier vielleicht auf das Problem, dass die Anzahl der Verbindungen, die ein Client zu ein- und demselben HTTP-Server erlaubt, beschränkt ist. Soweit ich das sehe, hast du zwar eigentlich nur 2 Verbindungen auf, aber möglicherweise liegt es auch ein einem Proxy, einem Router oder an einer Firewall dazwischen - was weiß ich ;-)

        Jedenfalls hätte ich noch eine andere Idee, wie du das implementieren könntest. Eigentlich brauchst du den Clienten ja nicht so ewig lang an dieser einen AJAX Verbindung hocken lassen, wo der Client dann 3-4 Minuten nichts empfängt und nur warten darf.

        Du könntest dich also mal mit den Prozess Kontroll-Funktionen auseinandersetzen. Ich denke da z.B. an folgendes Szenario: Bevor du den Transfervorgang per FTP startest, forkst du deinen PHP-Prozess und lässt ihn im Hintergrund des Servers weiterlaufen. Im Hintergrundprozess lässt du dann den FTP-Transfer laufen, der erste Prozess, an dem der Client sozusagen dranhängt kann sich dann einfach beenden und dem Clienten noch die Prozessnummer des Hintergrundprozesses mitteilen (alternativ hier mit Datenbank arbeiten).

        Nun läuft also der FTP-Transfer und es besteht keine Verbindung mehr zwischen Client und Server. Per Poll-Abfrage prüfst du dann ständig, wie groß die Datei schon ist (und zeigst dann nach Bedarf den Fortschrittsbalken an) und prüfst ebenso, ob der Hintergrundprozess noch am Laufen ist. Dazu einfach in der Prozessliste gucken (ps -A), die PID liegt dir beim Clienten oder in der Datenbank vor, je nachdem, wie du es implementiert hast. Ist der Hintergrundprozess dann beendet, so ist der FTP-Transfer auch zu Ende - du kannst dem Clienten sagen: Yuchuu, wir sind fertig! :)

        Die PCNTL Erweiterung für PHP ist allerdings keine Standard-Erweiterung, aber so wie du dich angehört hast, läuft das eh auf einem eigenen Server. Codebeispiele für das forken eines Prozesses mit PHP erhältst du, wenn du im Forumsarchiv 2006 nach "dennis jabber" suchst ;-)

        Viele Grüße aus Kanada,
          ~ Dennis.

        1. Hi Dennis!

          Hört sich sehr gut an! Gibt nur ein Problem: Der "Client", der also der Server, der die Datei downloaded bzw. uploaded, ist ein Windows-Rechner mit Apache und PHP! Das wird dann wohl nichts mit dem pcntl-Funktionen....

          Aber herzlichen Dank für den Tipp!

          Hm... Wie dedlfix schon erwähnt hat, stößt du hier vielleicht auf das Problem, dass die Anzahl der Verbindungen, die ein Client zu ein- und demselben HTTP-Server erlaubt, beschränkt ist. Soweit ich das sehe, hast du zwar eigentlich nur 2 Verbindungen auf, aber möglicherweise liegt es auch ein einem Proxy, einem Router oder an einer Firewall dazwischen - was weiß ich ;-)

          Also der Client ruft den Apache auf localhost auf... das ist also kein Problem, oder?

          Jedenfalls hätte ich noch eine andere Idee, wie du das implementieren könntest. Eigentlich brauchst du den Clienten ja nicht so ewig lang an dieser einen AJAX Verbindung hocken lassen, wo der Client dann 3-4 Minuten nichts empfängt und nur warten darf.

          OK!!! Da werde ich mal ein Test machen....

          Nun läuft also der FTP-Transfer und es besteht keine Verbindung mehr zwischen Client und Server. Per Poll-Abfrage prüfst du dann ständig, wie groß die Datei schon ist (und zeigst dann nach Bedarf den Fortschrittsbalken an) und prüfst ebenso, ob der Hintergrundprozess noch am Laufen ist. Dazu einfach in der Prozessliste gucken (ps -A), die PID liegt dir beim Clienten oder in der Datenbank vor, je nachdem, wie du es implementiert hast. Ist der Hintergrundprozess dann beendet, so ist der FTP-Transfer auch zu Ende - du kannst dem Clienten sagen: Yuchuu, wir sind fertig! :)

          Fast genauso habe ich es ja vor. Nur, dass ich die Verbindung leider nicht trennen kann... oder doch? Kann man eigentlich per PHP ein anderes Skript aufrufen und es einfach laufen lassen?!?!?

          Gruß und danke

          Daniel

          1. Hi DanielE,

            Aber herzlichen Dank für den Tipp!

            Arg, das dies unter Windows nicht funktioniert war mir bewusst - ich hab noch überlegt, ob ich das in mein Posting noch reinschreiben soll oder nicht *g*

            Also der Client ruft den Apache auf localhost auf... das ist also kein Problem, oder?

            Eigentlich nicht... Die meisten Browser sind so konfiguriert, sowieso keinen Proxy zu nutzen für localhost bzw. 127.0.0.1 - auch wenn für das Internet ein Proxy eingestellt ist. Ich glaube eher an die Beschränkung, dass du per AJAX nur einen Request an einen Server gleichzeitig machen darfst.

            Fast genauso habe ich es ja vor. Nur, dass ich die Verbindung leider nicht trennen kann... oder doch? Kann man eigentlich per PHP ein anderes Skript aufrufen und es einfach laufen lassen?!?!?

            Wenn wir jetzt mal davon ausgehen, dass ich mit oben genannter Einschränkung recht habe, dann müsstest du diese Verbindung trennen - unter Linux kannst du Anwendungen im Hintergrund starten mit einem

            exec("./anwendung &");

            Das & Zeichen danach schiebt die Anwendung in den Hintergrund. Ob das unter Windows funktioniert, oder ob es was anderes unter Windows gibt weiß ich nicht. Da müsstest du halt mal googeln.[1]

            In deinem Fall müsstest du wohl so etwas machen (unter Linux):

            exec("/pfad/zu/php-interpreter /pfad/zu/php-script &");

            Ob es zwingend notwendig ist weiß ich nicht, es hat sich aber als hilfreich erwiesen (siehe auch bereits benannte Threads im Archiv), in dem im Hintergrund gestarteten PHP-Script erst mal ein

            fclose(STDIN);
              fclose(STDOUT);
              flcose(STDERR);

            zu machen, da sich sonst das erste PHP-Script, das den Hintergrund Prozess gestartet hat, trotzdem totwartet, weil die Dateideskriptoren zu dem Hintergrund Prozess noch offen sind.

            [1] Ok, aus eigenem Interesse habe ich grade mal noch selber gegoogelt, "php windows exec background" schienen mir gute Stichworte zu sein, abgesehen von gefundenen Kommentaren im PHP-Manual, hielt ich diese Seite für sehr hilfreich.

            Viele Grüße aus Kanada,
              ~ Dennis.

            1. Hi Dennis,

              zu machen, da sich sonst das erste PHP-Script, das den Hintergrund Prozess gestartet hat, trotzdem totwartet, weil die Dateideskriptoren zu dem Hintergrund Prozess noch offen sind.

              [1] Ok, aus eigenem Interesse habe ich grade mal noch selber gegoogelt, "php windows exec background" schienen mir gute Stichworte zu sein, abgesehen von gefundenen Kommentaren im PHP-Manual, hielt ich diese Seite für sehr hilfreich.

              Wow, hört sich gut an, aber irgendwie ist der Aufwand eigentlich nicht mehr für so eine Progressbar gerechtfertigt, aber egal. Das juckt mir jetzt unter den Fingern... Konnte übrigens leider erst jetzt antworten, sorry. Werde ich aufjedenfall ausprobieren, weiß aber nicht so genau, wann ich es schaffe. Werde dich aber wissen, ob es funktioniert. Ich hoffe, dass der Thread so lange dann noch auf ist!

              Gruß

              Daniel

            2. Hi Dennis,

              es funktioniert!!! Meine Progessbar ist zwar noch nicht ideal, aber es funktioniert.

              [1] Ok, aus eigenem Interesse habe ich grade mal noch selber gegoogelt, "php windows exec background" schienen mir gute Stichworte zu sein, abgesehen von gefundenen Kommentaren im PHP-Manual, hielt ich diese Seite für sehr hilfreich.

              Ich führe folgenden Befehl aus:
              $proc = "start " . 'C:\Programme\xampp\php\php.exe' . " " . 'download.php ' . $_GET['downloadFile'];
              pclose(popen($proc, "r"));

              Einfach klasse. Genau, wie ich mir das vorgestellt habe!!!

              Herzlichen Dank!

              Gruß

              Daniel

              1. Hi DanielE,

                es funktioniert!!! Meine Progessbar ist zwar noch nicht ideal, aber es funktioniert.

                Hehe, freut mich :) Hat mich also meine wage Erinnerung doch nicht betrügt, mit AJAX darfst du zu einem Server zu einem Zeitpunkt nur eine Verbindung aufmachen.

                Ich führe folgenden Befehl aus:
                $proc = "start " . 'C:\Programme\xampp\php\php.exe' . " " . 'download.php ' . $_GET['downloadFile'];

                Interessant, wie kompliziert du das geschrieben kriegst *g* Unabhängig davon solltest du noch unbedingt escapeshellarg() verwenden, weil sonst ein Angreifer eventuell beliebige Befehle auf dem Zielsystem ausführen lassen kann - so ungefähr könnte das aussehen:

                $proc = "start C:\Programme\xampp\php\php.exe download.php " . escaleshellarg($_GET['download']);

                Wie prüfst du jetzt eigentlich, ob der Download-Prozess beendet ist? Eine Prozessliste wie ps -A unter Linux gibt es ja unter Windows AFAIK nicht, oder?

                Lässt du das rein über die Dateigröße laufen? Weil sonst könntest du dir auch überlegen noch eine Art Lockfile anzulegen und mit Spielereien wie touch() sicherstellen, dass der Download-Prozess immer noch läuft und nicht abgeschmiert ist...

                Viele Grüße aus Kanada,
                  ~ Dennis.

                1. Hi Dennis,

                  Interessant, wie kompliziert du das geschrieben kriegst *g* Unabhängig davon solltest du noch unbedingt escapeshellarg() verwenden, weil sonst ein Angreifer eventuell beliebige Befehle auf dem Zielsystem ausführen lassen kann - so ungefähr könnte das aussehen:

                  $proc = "start C:\Programme\xampp\php\php.exe download.php " . escaleshellarg($_GET['download']);

                  Ist in Ordnung. Werde ich noch hinzufügen... ist ja net sonderlich schwierig...

                  Wie prüfst du jetzt eigentlich, ob der Download-Prozess beendet ist? Eine Prozessliste wie ps -A unter Linux gibt es ja unter Windows AFAIK nicht, oder?

                  Hmm, da kann ich nur sagen: Zauberrei...

                  Lässt du das rein über die Dateigröße laufen? Weil sonst könntest du dir auch überlegen noch eine Art Lockfile anzulegen und mit Spielereien wie touch() sicherstellen, dass der Download-Prozess immer noch läuft und nicht abgeschmiert ist...

                  ... OK, keine Zauberei! Es ist eher ein wenig geraten;) Also ich mache folgendes: Ich öffne ja den Download-Prozess per popen! Die Dateigröße steigt dann ja. Per Ajax mache ich alle 4 sek. eine Abfrage, wie groß die Datei ist. Naja, eigentlich bekomme ich nur gesagt, wieviel Prozent der Datei gedownloaded bzw. geuploaded ist. Innerhalb der Serveranwendung habe ich nämlich einen Service implementiert, der mir sagt, wie groß eine Datei ist. In der Clientanwendung rufe ich diesen Service auf und noch zusätzlich filesize für die lokale Datei, die gedownloaded wird. Dann berechne ich einen Prozentwert. Aber wie weiß ich jetzt, dass die Datei vollständig gedownloaded ist? Also, wenn der Download problemlos funktioniert, bekomme ich irgendwann 100 von Server zurück, weil 100%  der Datei gedownloaded ist. Das ist ein Indikator. Ein zweiter ist eher ein vermuteter Indikator. Ich frage alle 4 sek. die Dateigröße ab. Wenn die Prozentzahl sich 5 mal nicht ändert, dann gab es einen Fehler und ich breche das ganze mit einer Fehlermeldung ab.

                  Funktioniert recht gut!

                  Gruß

                  Daniel

                  Gruß

                  Daniel