Progresión de una subida (upload) en sesión

Cuando la opción de configuración session.upload_progress.enabled está activa, PHP será capaz de rastrear la progresión de un fichero en curso de subida (upload). Esta información no es particularmente útil para la petición de subida en sí, pero durante la subida, una aplicación puede enviar una petición POST separada (por ejemplo, mediante XHR) para verificar el estado de esta subida.

La progresión de la subida estará disponible en la variable superglobal $_SESSION cuando la subida está en curso, y durante un envío en método POST de una variable con el mismo nombre que el definido en la opción de configuración INI session.upload_progress.name. Cuando PHP detecta una petición POST de este tipo, llenará un array en $_SESSION, donde el índice es un valor concatenado de las opciones de configuración session.upload_progress.prefix y session.upload_progress.name. La clave se recupera típicamente leyendo estas configuraciones INI, es decir:

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

Asimismo, es posible cancelar la subida actual definiendo la clave $_SESSION[$key]["cancel_upload"] al valor true. Durante la subida de varios ficheros en la misma petición, esta acción solo cancelará el fichero actualmente en curso de subida, así como aquellos en espera de subida, pero no cancelará las subidas terminadas con éxito. Cuando una subida es cancelada utilizando este método, la clave error del array $_FILES será definida a UPLOAD_ERR_EXTENSION.

Las opciones de configuración INI session.upload_progress.freq y session.upload_progress.min_freq controlan la frecuencia de actualización de las informaciones de progresión de subida. Con una configuración razonable de estas 2 opciones, el sobrecoste en términos de carga es casi nulo.

Ejemplo #1 Ejemplo

Ejemplo de estructura del array que contiene las informaciones de subida.

<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>

Los datos almacenados en sesión se asemejarán a:

<?php
$_SESSION
["upload_progress_123"] = array(
"start_time" => 1234567890, // La hora de la petición
"content_length" => 57343257, // Longitud del contenido POST
"bytes_processed" => 453489, // Cantidad de bytes recibidos y procesados
"done" => false, // true cuando el manejador POST ha terminado, con éxito o no
"files" => array(
0 => array(
"field_name" => "file1", // Nombre del campo <input/>
// Los 3 elementos siguientes son equivalentes a los en $_FILES
"name" => "foo.avi",
"tmp_name" => "/tmp/phpxxxxxx",
"error" => 0,
"done" => true, // True cuando el manejador POST ha terminado de manejar este fichero
"start_time" => 1234567890, // La hora de inicio de petición
"bytes_processed" => 57343250, // Cantidad de bytes recibidos y procesados para este fichero
),
// Otro fichero, en curso de subida, en la misma petición
1 => array(
"field_name" => "file2",
"name" => "bar.avi",
"tmp_name" => NULL,
"error" => 0,
"done" => false,
"start_time" => 1234567899,
"bytes_processed" => 54554,
),
)
);

Advertencia

El almacenamiento en búfer de la petición del servidor web debe estar desactivado para el buen funcionamiento de esta funcionalidad, de lo contrario PHP solo verá el fichero una vez que esté completamente subido. Los servidores como Nginx son conocidos por almacenar en búfer grandes peticiones.

Precaución

Las informaciones de progresión de la subida son escritas en sesión antes de que un script sea ejecutado. Por consecuencia, cambiar el nombre de sesión mediante ini_set() o session_name() dará una sesión sin las informaciones de progresión de la subida.

add a note

User Contributed Notes 11 notes

up
165
s.zarges
13 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
63
howtomakeaturn
10 years 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
24
Anonymous
12 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
14
isius
12 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
6
jortsc at gmail dot com
11 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
5
nihaopaul at gmail dot com
12 years ago
it should be noted that the hidden element come before the file element otherwise you wont get any updates.
up
3
Anonymous
12 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
8 years 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
0
raptor98 at email dot cz
9 months ago
Warning:
Do not change session.save_path and session.name (in your application)!

The request for upload info must by POST with same value and name of your hidden input (session.upload_progress.name).

Info:
It works under IIS /FastCGI (at PHP 5.4 and PHP 8.2, other not tested).
up
1
StrateGeyti
10 years 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
1
ricki at rocker dot com
10 years ago
session.upload_progress updates completely ignore custom session handlers set via session_set_save_handler()
To Top