ConFoo Montreal 2017 Calling for Papers

Session-Upload-Fortschritt

Wenn die session.upload_progress.enabled Ini-Option aktiviert ist, kann PHP den Upload-Fortschritt der hochgeladenen Dateien verarbeiten. Die von PHP bereitgestellten Daten sind für den eigentlichen Upload-Vorgang nicht nutzbar. Um den Status des Uploads zu verarbeiten, muss die Anwendung eine POST-Anfrage an einen separaten Endpunkt (zum Beispiel via XHR) ausführen.

Der Upload-Fortschritt steht in der Superglobalen $_SESSION zur Verfügung, wenn der Upload-Vorgang stattfindet und wenn ein POST-Feld, mit dem in der Ini-Konfiguration session.upload_progress.name hinterlegten Namen enthalten ist. Wenn PHP eine solche POST-Anfrage erkennt, wird ein Array mit Informationen in der $_SESSION hinterlegt. Die Information wird mit dem aus den Ini-Konfigurationen session.upload_progress.prefix und session.upload_progress.name zusammengesetzten Index gespeichert. Der Schlüssel wird dabei typischerweise aus den Ini-Konfigurationen zusammengesetzt, zum Beispiel:

<?php
$key 
ini_get("session.upload_progress.prefix") . $_POST[ini_get("session.upload_progress.name")];
var_dump($_SESSION[$key]);
?>

Es ist auch möglich, den Upload-Vorgang, durch setzen des Session-Wertes $_SESSION[$key]["cancel_upload"] auf TRUE, abzubrechen. Wenn mehrere Dateien in der gleichen Anfrage übertragen werden, wird dabei nur die in der Verarbeitung befindliche Datei und alle ausstehenden Dateien abgebrochen. Schon erfolgreich übertragene Dateien werden nicht entfernt. Wenn ein Upload auf diese Weise abgebrochen wird, enthält der error Schlüssel des $_FILES Array den Wert UPLOAD_ERR_EXTENSION.

Die Ini-Konfigurationen session.upload_progress.freq und session.upload_progress.min_freq steuern, wie häufig die Upload-Fortschrittsinformationen neu berechnet werden sollen. Mit angemessenen Einstellungen bei diesen zwei Optionen ist der Aufwand für diese Funktion sehr gering.

Beispiel #1 Beispiel-Informationen

Beispiel für den Formularaufbau des Upload-Fortschritts.

<form action="upload.php" method="POST" enctype="multipart/form-data">
 <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
 <input type="file" name="file1" />
 <input type="file" name="file2" />
 <input type="submit" />
</form>

Die gespeicherten Daten in der Session sehen wie folgt aus:

<?php
$_SESSION
["upload_progress_123"] = array(
 
"start_time" => 1234567890,   // Anfragezeitpunkt
 
"content_length" => 57343257// POST Gesamtdatenmenge (in Bytes)
 
"bytes_processed" => 453489,  // Menge der empfangenen und verabreiteten Daten (in Bytes)
 
"done" => false,              // true wenn die POST Datenverarbeitung beendet ist (erfolgreich oder nicht)
 
"files" => array(
  
=> array(
   
"field_name" => "file1",       // Name des <input/> Feldes
   // Die nächsten drei Elemente entsprechen den Angaben in $_FILES
   
"name" => "foo.avi",
   
"tmp_name" => "/tmp/phpxxxxxx",
   
"error" => 0,
   
"done" => true,                // true wenn die POST Datenverarbeitung dieser Datei beendet ist
   
"start_time" => 1234567890,    // Zeitpunkt wann die Verarbeitung der Datei begonnen hat
   
"bytes_processed" => 57343250// Menge der empfangenen und verabreiteten Daten dieser Datei (in Bytes)
  
),
  
// Eine weitere, noch nicht Komplett hochgeladene Datei, der selben Anfrage
  
=> array(
   
"field_name" => "file2",
   
"name" => "bar.avi",
   
"tmp_name" => NULL,
   
"error" => 0,
   
"done" => false,
   
"start_time" => 1234567899,
   
"bytes_processed" => 54554,
  ),
 )
);

Warnung

In der Anfrage des Servers muss Pufferung deaktiviert sein, damit dies richtig funktioniert. Server wie z.B. Nginx sind bekannt dafür, große Anfragen zu puffern.

add a note add a note

User Contributed Notes 16 notes

up
96
s.zarges
4 years ago
Note, this feature doesn't work, when your webserver is runnig PHP via FastCGI. There will be no progress informations in the session array.
Unfortunately PHP gets the data only after the upload is completed and can't show any progress.

I hope this informations helps.
up
21
howtomakeaturn
1 year ago
ATTENTION:

Put the upload progress session name input field BEFORE your file field in the form :

  <form action="upload.php" method="POST" enctype="multipart/form-data">
  <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
  <input type="file" name="file1" />
  <input type="file" name="file2" />
  <input type="submit" />
  </form>

If you make it after your file field, you'll waste a lot of time figuring why (just like me ...)

The following form will make you crazy and waste really a lot of time:

<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
<input type="submit" />
</form>

DON'T do this!
up
20
gerd dot randolf at web dot de
4 years ago
Note that this will be available from PHP 5.4 on. It won't work in PHP 5.3 or earlier.
up
12
Anonymous
3 years ago
While the example in the documentation is accurate, the description is a bit off. To clarify:

PHP will populate an array in the $_SESSION, where the index is a concatenated value of the session.upload_progress.prefix and the VALUE of the POSTed session.upload_progress.name variable.
up
3
ricki at rocker dot com
1 year ago
session.upload_progress updates completely ignore custom session handlers set via  session_set_save_handler()
up
10
isius
3 years ago
If you're seeing
"PHP Warning:  Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0",
then a misplaced input could be the cause. It's worth mentioning again that the hidden element MUST be before the file elements.
up
4
wojbach at o2 dot pl
4 years ago
"session.upload-progress.name" -> whether here shouldn't be a underscore instead of a dash
up
1
StrateGeyti
1 year ago
It seems like if you send a form with the field like :

<?php echo '<input type="hidden" name="'.ini_get('session.upload_progress.name') .'" value="123" />'?>

without any field type "file", the server respons will be an 500 error.
up
2
Anonymous
3 years ago
dont't forget, that the session has to be initialized before the form is generated, otherwise the mentioned example above won't work.
up
1
alice at librelamp dot com
1 month ago
There were two gotchas that got me with implementing this.

The first - if you use session_name() to change the name of sessions, this will not work. I discovered this by looking at phpinfo() and seeing that is saw a different session name.

At least in Apache, a better way to set the session is in your apache config use

php_value session.name "your custom name"

It goes within the Directory directive, might work in .htaccess - I don't know.

-=-

Secondly - in apache, don't use mod_mpm_prefork.so

That was the problem I had, that's the default in CentOS 7.

The problem is it causes Apache to wait with any additional requests until the upload is finished.

Commenting that module out and using mod_mpm_worker.so instead fixed that problem, and the progress meter worked.
up
1
adri74 at hotmail dot fr
6 months ago
It seems like defining a session name before starting the session makes the $_SESSION['upload_progress...'] not to work any more !

session_name('session');
session_start();

(in both the upload page, and the XHR request)
up
0
jortsc at gmail dot com
2 years ago
Note that if you run that code and you print out the content of $_SESSSION[$key] you get an empty array due that session.upload_progress.cleanup is on by default and it  cleans the progress information as soon as all POST data has been read.

Set it to Off or 0 to see the content of $_SESSION[$key].
up
-2
nihaopaul at gmail dot com
4 years ago
it should be noted that the hidden element come before the file element otherwise you wont get any updates.
up
-3
wilsonr at st dot com
1 year ago
If you have upload progress enabled in your php.ini, and you have

<form enctype="multipart/form-data" ...
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" ...

in your form, but you DON'T specify an input with 'type="file"', you may lose your session ID. I am using PHP 5.5 and I lose my session ID on the second loading of such a page. To prevent this, you can use a dummy input as follows:

<form enctype="multipart/form-data" ... >
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" ... />
    <input type="file"' name="dummy" style="display="none;" ... />
up
-21
takeone
4 years ago
IE6 does not inherit session when you launch new browser from start menu or shortcut.It's the feature.
It is recommended that upload form and progress bar are on same window.
To Top