Progressbars in PHP-Projekten

Okt 14th, 2008 | By | Category: Allgemein

Einführung

Progressbars sind mittlerweile ein gängiges Mittel, um Statusanzeigen zu realisieren. Seit 2003 nutze ich diese in verschiedenen Projekten, jedoch waren die Mittel, diese zu regeln, in der Vergangenheit eher holperig, unkomfortabel oder instabil gelöst. Musste in Projekt umziehen oder gab es neue Browser oder auch Flash-Versionen, begann die Konfiguration und das Rätselraten von neuem. CGI und Flash oder per Output-Buffer gesteuerte Javascript-Bars waren immer instabil und hielten selten länger als ein Jahr in einem Projekt aus.

Dank der “Erfindung” von Ajax war man daraufhin in der Lage, für Prozesse, die nach einem Request durchgeführt wurden, bereits gute und flüssige Prozessanzeigen zu realisieren. In verschiedenen Projekten habe ich beispielsweise Datensammlungen oder das Erstellen von ZIP-Archiven visuell dargestellt.

Mit der PHP-Version 5.2 lässt sich nun auch über die Extension APC ein Upload mit einer Progress-Anzeige sinnvoll lösen, denn im Wesentlichen verändert sich nichts. Um dieses Feature zu nutzen, sind jedoch ein paar Vorbereitungen nötig:

1. Installation von APC

Benötigt werden:

  • Root-Zugriff auf die Kommandozeile
  • ein installiertes und auf Kommandozeilenebene funktionsfähiges PEAR bzw. PECL
  • Internet-Zugriff

Zunächst einmal wird APC mittels PECL installiert:

testserver:~# pecl install apc

Bei der darauffolgenden Frage die Option APCX ändern auf “NO”

Use apxs to set compile flags (if using APC with Apache)? [yes] : no

Nun folgen etliche Zeilen Kompilierung und Installation. Abhängig vom System (in meiner Debian-Testumgebung ist es zwingend notwendig) muss in die php.ini bzw. im Debian in eine separate Datei

extension=apc.so

eingetragen werden.

AUsschnitt aus der PHP-Info zum APC-Eintrag

Ausschnitt aus der PHP-Info zum APC-Eintrag

Ein Neustart des Webservers sollte nun – oh Wunder – die Extension geladen haben. Dies lässt sich am einfachsten Über eine Ausgabe der phpinfo(); prüfen, hier sollte es einen neuen Eintrag zu APC geben. Sofern APC-Support “enabled” ist, kann es weitergehen mit dem PHP-Teil der Installation. Sollte das Modul noch nicht aktiviert sein, hilft in der Regel ein Basiseintrag in der php.ini:

[APC]
apc.enable_cli=0
apc.enabled=1
apc.num_files_hint=1024
apc.optimization=0
apc.rfc1867=1
apc.shm_segments=1
apc.shm_size=128
apc.ttl=7200
apc.user_ttl=7200

2. PHP-Dateien und deren Funktionsweise

Grundsätzlich funktioniert das Uploaden nun in der Weise, dass PHP in der Lage ist, einen weiteren Request aus der gleichen Quelle parallel zum laufenden Request zu beantworten. Dies bedeutet, dass man eigentlich nur dafür sorgen muss, dass PHP während des Uploads brav antwortet, wieviel Upload statt fand. Hierfür sind folgende Codeschnipsel notwendig:

Das Formular in der HTML-Datei:

<form action="upload.php" method="post" target="uploadFrame" enctype="multipart/form-data">

<input type="file" name="upload" />
<input type="hidden" name="APC_UPLOAD_PROGRESS" value="<?php echo
md5(uniqid(rand(), true)); ?>" />
<button type="submit" onclick="this.disabled=true; setTimeout('requestStatus(\''+this.form.APC_UPLOAD_PROGRESS.value+'\')', 1000);">Abschicken</button>
</form>

Zu beachten ist, dass APC mit dem versteckten Feld APC_UPLOAD_PROGRESS mitgeteilt wird, wie die eindeutige Id für diesen Upload lautet. Der Bezeichner muss mit der Angabe apc.rfc1867_name in der PHP-Konfiguration überein stimmen.

Zusätzlich muss in den HTML-Code ein IFrame eingebaut werden, an welches die Upload-Datei geschickt wird. Dies wird notwendig, weil alle gängigen Browser durch das Abschicken des Formulars im gleichen Fenster die Seite blockieren würde und Änderungen im HTML-Code dann nicht mehr möglich sind.

<iframe src="blank.html" name="uploadFrame" style="display:none"></iframe>

Zusätzlich sollte fehlt natürlich noch ein Platz, um den Upload-Status anzuzeigen. Hier sind mehrere Varianten denkbar, für einen ersten Test reicht zunächst erst einmal ein leeres DIV.

<div id="divStatus"></div>

Die Datei für den Empfang des Uploads (upload.php)

An dieser simplen Funktion ändert sich genau nichts, der Upload funktioniert hier genau gleich:


<?php
if (isset($_FILES['upload'])) {
move_uploaded_file($_FILES['upload']['tmp_name'], 'upload/'.$_FILES['upload']['name']);
}
?>

Natürlich muss man hier selbst für Sicherheit etc. sorgen, aber im Grundsatz ist der Upload identisch.

Die Datei für die Statusmeldung (status.php)

Ihre einzige Aufgabe ist es, den Upload anhand der eindeutigen Id zu identifizieren und mit Hilfe der Funktion apc_fetch() den aktuellen Status auszulesen. Dieser muss dann nur noch entsprechend aufbereitet werden, um im richtigen Format an die HTML-Seite übermittelt zu werden:

<?php
$arr_status = apc_fetch('upload_'.$_GET['
str_apcId']);
printf("<pre>%s</pre>", print_r($arr_status, true));
?>

Der Javascript-Teil

function requestStatus(str_apcId)' {

var request = new Request({
url: ‘/status.php?apcId=’+str_apcId,
onComplete: function(responseText) {
$(‘uploadStatus’).innerHTML = responseText;
}
}).send();
}

Der Javascript-Part sollte hier sehr individuell ausfallen, dies ist insbesondere abhängig vom genutzten Javascript-Framework, von der Art, den Status anzuzeigen sowie den technischen Möglichkeiten. Das gezeigte Beispiel wäre eine Möglichkeit in MooTools, aber auch hier gilt, dass sowohl die Schnittstelle zum Server als auch das Javascript abgesichter sein sollten gegen einen Fremdzugriff.

Quellen:

http://www.debianblogs.com/debian_apc_alternative_php_cache

http://www.coder-wiki.de/HowTos/PHP-AJAX-Upload-Fortschritt

http://mootools.net/docs/Request/Request

Update:

Wer Probleme bei der Installation mit PECL bekommt, sollte überprüfen, ob folgende Pakete installiert und verfügbar sind:
php5-dev
apache2-dev
build-essentials

Die Namen der Pakete sind zwischen den Distributionen unterschiedlich, wichtig ist, dass sowohl von PHP als auch vom installierten Apache die Development-Pakete zur Verfügung stehen und alle notwendigen Bibliotheken installiert sind.

Tags: , , , , , , , ,

Leave Comment