Aussetzer bei is_file() ?

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Aussetzer bei is_file() ?

    Hallo.

    Ich stelle im Moment ein sehr merkwürdiges Verhalten in einem Skript fest, das ich mir absolut nicht erklären kann.

    Es geht um ein Unterschriften-System für den Erhalt von Ware (ähnlich DHL&Co.) auf Basis von PHP/JavaScript/AJAX.

    Dabei nutze ich die Zeichenfunktionalität von CANVAS: Ich erstelle ein Canvas-Objekt, auf dem der Empfänger unterschreibt.
    Man klickt auf einen Button und über AJAX wird das Bild mit der Unterschrift gespeichert.

    Danach wird mit location.href zu einem Skript weitergeleitet, das einen Lieferschein als PDF erstellt. Als Krönchen möchte ich, dass das Bild mit der Unterschrift direkt auf dem Lieferschein eingefügt wird.

    Prinzipiell funktioniert alles einwandfrei. In 8 von 10 Fällen läuft das Skript absolut perfekt.

    In den anderen 2 Fällen kann es zu 2 verschiedenen Fehlern kommen:

    1.
    Das Bild mit der Unterschrift wird nicht gespeichert. Ich habe hierfür noch keine Erklärung, denn das Speichern über das AJAX-Skript erfolgt innerhalb von 4 Zeilen, wo kein Fehler drin sein kann.
    Ich denke eher, dass es am Browser (FF) liegt und dieser manche AJAX-Anweisungen nicht richtig ausführt.

    Wie dem auch sei. Problematischer finde ich den zweiten Fall.

    2.
    Das Bild ist zwar da, aber trotzdem gibt is_file() anscheinend FALSE zurück.

    Ich arbeite bereits mit sleep(), um der Speicherung Zeit zu geben, die Datei "in Ruhe" abzulegen. Doch auch damit hatte ich keinen 100%igen Erfolg.

    Um ganz sicher zu gehen, dass die Speicherung Zeit genug hat, habe ich folgendes geschrieben:

    Code:
    $timer_s = time();
    while ( (!is_file("unterschrift.jpg")) && (time() < ($timer_s+10)) )
    {
       sleep (1);
    }
     
    if (time() > ($timer_s+10))
    {
       die ("Zeit abgelaufen!");
    }
     
    if (is_file("unterschrift.jpg"))
    {
       // Lieferschein schreiben
    }
    else
    {
       die ("Bild ist nicht da!");
    }
    Also: Solange die Datei nicht da ist und nicht min. 10 Sekunden vergangen sind, soll 1 Sekunde gewartet werden. Die 10-Sekunden-Grenze habe ich gesetzt, falls der oben genannte 1. Fehlerfall eintritt und die JPG wirklich nicht geschrieben wurde.

    Nun müsste man doch annehmen, dass es lediglich 2 Möglichkeiten gibt, wie das Skript beendet wird: Entweder rennt das Skript ins die() mit der Fehlermeldung "Zeit abgelaufen!" oder der Lieferschein wird erstellt.

    Und nun wird's freaky.
    Manchmal endet das Skript mit der Fehlermeldung "Bild ist nicht da!"!

    Wie kann das sein? Hinter die WHILE-Schleife kommt das Skript doch nur, wenn entweder die Datei da ist oder die 10-Sekunden-Grenze überschritten wurde.

    Ist die Datei da, kann der Lieferschein erstellt werden. Wurden die 10 Sekunden überschritten, muss das Skript mit "Zeit abgelaufen!" enden.

    Ich erspare mir nun erst einmal das Posten des Quellcodes, da dieser in einem großen Projekt steckt und ich erst die relevanten Stellen herauskopieren und "lesbar" machen müsste, was ziemlich viel Arbeit ist.

    Vielleicht hat ja jetzt schon jemand eine Idee, wo der Fehler (oder wo mein Fehler?) liegt.

    Danke im Voraus.

    cya

  • #2
    Ich arbeite bereits mit sleep(), um der Speicherung Zeit zu geben, die Datei "in Ruhe" abzulegen. Doch auch damit hatte ich keinen 100%igen Erfolg.
    Darum:
    PHP: clearstatcache - Manual
    Wir werden alle sterben

    Kommentar


    • #3
      Danke. Klingt super. Funktioniert aber leider nicht.

      Könnte es etwas mit dem Festplatten-Cache o.ä. zu tun haben? Gibt's flush() für das Schreiben von Dateien?

      cya

      Kommentar


      • #4
        Zitat von sallow2001 Beitrag anzeigen
        Man klickt auf einen Button und über AJAX wird das Bild mit der Unterschrift gespeichert.

        Danach wird mit location.href zu einem Skript weitergeleitet ...
        Dieses "danach" heißt hoffentlich "wenn der AJAX-Request erfolgreich beendet wurde, was bedeutet, dass das Bild ganz sicher gespeichert wurde".

        Ich denke eher, dass es am Browser (FF) liegt und dieser manche AJAX-Anweisungen nicht richtig ausführt.
        Firebug!

        Ich arbeite bereits mit sleep(), um der Speicherung Zeit zu geben, die Datei "in Ruhe" abzulegen.
        Du solltest besser den Client darauf warten lassen, dass sein AJAX-Request erfolgreich war, s.o.

        Manchmal endet das Skript mit der Fehlermeldung "Bild ist nicht da!"! Wie kann das sein?
        Wenn time() == $timer_s ist, wird die While-Schleife beendet, denn time() < $time_s ergibt false.
        Drei Zeilen später ergibt time() > $time_s ebenfalls false.

        Merke: Zwischen kleiner als und größer als liegt oft ein gleich.

        Kommentar


        • #5
          Zitat von onemorenerd Beitrag anzeigen
          dass das Bild ganz sicher gespeichert wurde".
          "ganz sicher" kann ich nicht sagen, denn wie ich bereits schrieb, kann es auch mal vorkommen, dass das Bild gar nicht gespeichert wird. (Das ist aber sehr selten der Fall.)

          Aber ansonsten kann ich Deine Frage mit "ja" beantworten. Die Weiterleitung erfolgt natürlich nach dem AJAX-Aufruf.

          Zitat von onemorenerd Beitrag anzeigen
          Du solltest besser den Client darauf warten lassen, dass sein AJAX-Request erfolgreich war, s.o.
          Meinst Du jetzt explizit einen Warte-Befehl setzen (wenn ja: Welchen?) oder meinst Du die Reihenfolge der Abarbeitung?

          Zitat von onemorenerd Beitrag anzeigen
          time() == $timer_s
          Stimmt. So einfach kann es sein. Danke.

          Das erklärt aber leider nicht, wieso selbst nach 5 oder 10 Sekunden Wartezeit die Datei immer noch nicht geschrieben wurde.

          BTW:
          Wenn ich nach der Anzeige "Bild ist nicht da" mit ALT+TAB in den Window************plorer wechsle, ist die Datei wirklich noch nicht da. Kurz danach steht sie dann dort. Das könnte zwar auch an der Verzögerung der Anzeige im Window************plorer liegen, doch merkwürdig finde ich's schon. Erst nach sooo langer Zeit...!?

          cya

          Kommentar


          • #6
            Windows! Da wundert mich gar nichts mehr.
            Dann tippe ich mal blind aufs Filesystem ... wird wohl das Rausschreiben verzögern, evtl. sogar wegen der Aufrufe von file_exists().
            Eine Lösung wäre, die Datei zumindest vorerst im RAM zu halten, also z.B. memcache, oder eine DB zu nutzen.

            clearstatcache() ist übrigens überflüssig, weil nichts gecacht wird, solange die Datei nicht existiert.

            Kommentar


            • #7
              clearstatcache() ist übrigens überflüssig, weil nichts gecacht wird, solange die Datei nicht existiert.
              Einspruch:

              Wenn die Datei beim ersten Versuch nicht gefunden wird, speichert PHP den Zustand in einen internen stat Cache. Nachfolgende Zugriffe (z.B. in einer Schleife) werden immer nur auf den Cache zugreifen und nicht auf das Dateisystem.

              Also:
              Gehts hier ganz sicher nicht ohne: clearstatcache()


              Außer, da hätte sich in den letzten Jahren im PHP was verändert......

              PS:
              Ich sehe gerade, die englische Doku hat sich geändert!
              Zuletzt geändert von combie; 27.10.2010, 11:29.
              Wir werden alle sterben

              Kommentar


              • #8
                Widerspruch:

                Aus dem Manual: "You should also note that PHP doesn't cache information about non-existent files. So, if you call file_exists() on a file that doesn't exist, it will return FALSE until you create the file."

                Kommentar


                • #9
                  Hab's unter Linux getestet: Beim 7. Aufruf kam "Zeit abgelaufen!". Die Datei wurde wirklich nicht erstellt.

                  Das gibt's doch nicht.

                  Das kann dann ja wirklich nur am FF liegen, denn sonst würde ja die anderen Aufrufe nicht so wunderbar klappen.

                  Vielleicht klemmt der .send-Befehl? *stöhn*


                  cya

                  Kommentar


                  • #10
                    Was sagt denn Firebug dazu?

                    Kommentar


                    • #11
                      Schon mal das $_FILES['formfeldname']['error'] überprüft?

                      Widerspruch:
                      Ich habe der deutschen Doku geglaubt.

                      Die englische wurde auch erst mit PHP5.3 geändert denn vorher waren die beiden gleich lautend.
                      Zuletzt geändert von combie; 27.10.2010, 11:36.
                      Wir werden alle sterben

                      Kommentar


                      • #12
                        Zitat von onemorenerd Beitrag anzeigen
                        Was sagt denn Firebug dazu?
                        Keine Fehler. AJAX-POST wird korrekt gesendet.

                        Demnach müsste es am PHP-Skript liegen, das die Daten entgegennimmt und das Bild speichert.

                        Aber was soll an

                        Code:
                        <?php
                        $strData = base64_decode(rawurldecode($_POST['data']));
                        $p_canvasfilepointer = fopen($_GET['nummer'] . ".jpg", "wb");
                        fwrite($p_canvasfilepointer, $strData);
                        fclose($p_canvasfilepointer);
                        ?>
                        schon falsch sein??
                        (Parameter, Header und data stimmen lt. Firebug!)


                        Zitat von combie Beitrag anzeigen
                        Schon mal das $_FILES['formfeldname']['error'] überprüft?
                        Sorry, verstehe nicht, was Du meinst.

                        cya


                        edit:
                        Würde sich jemand die Zeilen ansehen und es testen, wenn ich alles mal extrahiere und zum Download bereitstelle?
                        (Wenn nicht, spare ich mir die Tipperei lieber. )

                        Ich muss gestehen, dass ich eh nicht so der JavaScript-/AJAX-Fan bin und normalerweise auch nicht mit dem FF arbeite.
                        Zuletzt geändert von sallow2001; 27.10.2010, 11:56.

                        Kommentar


                        • #13
                          file_put_contents() würde auch genügen.

                          Übrigens ist es kreuzgefährlich, einen GET-Parameter unbesehen als Dateinamen zu verwenden.

                          Kommentar


                          • #14
                            Sorry, verstehe nicht, was Du meinst.
                            OK..
                            Hatte verstanden, das du es per Upload machst, sehe jetzt, dass dem nicht so ist
                            Wir werden alle sterben

                            Kommentar


                            • #15
                              Zitat von onemorenerd Beitrag anzeigen
                              file_put_contents() würde auch genügen.
                              Ok, aber ob's dadurch besser (funktionieren) wird?

                              Zitat von onemorenerd Beitrag anzeigen
                              Übrigens ist es kreuzgefährlich, einen GET-Parameter unbesehen als Dateinamen zu verwenden.
                              Schon klar. Es handelt sich aber um ein internes Skript...da mache ich mir um Angriffe eher weniger (= gar keine) Sorgen.

                              Sonst noch irgendwelche Ideen?

                              cya

                              Kommentar

                              Lädt...
                              X