mirror of
https://github.com/php/doc-es.git
synced 2026-03-24 07:22:16 +01:00
* Fix typo add ref warn.deprecated.feature-8-1-0 * Remove <para> in invalid places * Fix language snippets
397 lines
20 KiB
XML
397 lines
20 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: 3944dc63330edde959cfd3e7d113c999cbec10ff Maintainer: PhilDaiguille Status: ready -->
|
|
<!-- Reviewed: no -->
|
|
|
|
<chapter xml:id="features.file-upload" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Gestión de cargas de ficheros</title>
|
|
|
|
<sect1 xml:id="features.file-upload.post-method">
|
|
<title>Cargas de ficheros por método POST</title>
|
|
|
|
<simpara>
|
|
Esta funcionalidad permite a las personas subir tanto texto como ficheros binarios. Con las funciones de identificación y manipulación de ficheros de PHP, se tiene el control total para definir quién tiene derecho a subir, pero también qué se hará con el fichero una vez que se haya subido.
|
|
</simpara>
|
|
<simpara>
|
|
PHP es capaz de recibir ficheros emitidos por un navegador conforme a la norma RFC-1867.
|
|
</simpara>
|
|
|
|
<note>
|
|
<title>Notas de configuración</title>
|
|
<para>
|
|
Véase también las directivas
|
|
<link linkend="ini.file-uploads">file_uploads</link>,
|
|
<link linkend="ini.upload-max-filesize">upload_max_filesize</link>,
|
|
<link linkend="ini.upload-tmp-dir">upload_tmp_dir</link>,
|
|
<link linkend="ini.post-max-size">post_max_size</link> y
|
|
<link linkend="ini.max-input-time">max_input_time</link> en &php.ini;
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
PHP también soporta la carga por el método PUT como en el navegador <productname>Netscape Composer</productname> y <productname>Amaya</productname> del W3C. Consulte el capítulo sobre el
|
|
<link linkend="features.file-upload.put-method">soporte del método PUT</link>.
|
|
</para>
|
|
|
|
<para>
|
|
<example>
|
|
<title>Formulario de carga de fichero</title>
|
|
<para>
|
|
Un formulario de carga de ficheros puede ser construido creando un formulario específico como este:
|
|
</para>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<!-- El tipo de codificación de datos, enctype, DEBE ser especificado como se indica a continuación -->
|
|
<form enctype="multipart/form-data" action="_URL_" method="post">
|
|
<!-- MAX_FILE_SIZE debe preceder al campo input de tipo file -->
|
|
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
|
|
<!-- El nombre del elemento input determina el nombre en el array $_FILES -->
|
|
Envíe este fichero: <input name="userfile" type="file" />
|
|
<input type="submit" value="Enviar el fichero" />
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
<para>
|
|
<literal>_URL_</literal> en el ejemplo anterior debe ser reemplazado y apuntar a un fichero PHP.
|
|
</para>
|
|
<para>
|
|
El campo oculto <literal>MAX_FILE_SIZE</literal> (medido en bytes) debe preceder al campo input de tipo file y su valor representa el tamaño máximo aceptado del fichero por PHP. Este elemento de formulario debe ser siempre utilizado, ya que permite informar al usuario que la transferencia deseada es demasiado grande antes de llegar al final de la carga. Tenga en cuenta que este parámetro puede ser "engañado" fácilmente desde el lado del navegador, por lo que no se debe confiar en él, tratándose finalmente de una funcionalidad de conveniencia del lado del cliente. El parámetro PHP (del lado del servidor) sobre el tamaño máximo de un fichero cargado, no puede ser engañado.
|
|
</para>
|
|
</example>
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Asegúrese de que su formulario de carga de fichero contenga <literal>enctype="multipart/form-data"</literal>, de lo contrario, el fichero no será cargado.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
La variable global <varname>$_FILES</varname> contendrá toda la información sobre el fichero cargado. Su contenido se detalla en nuestro ejemplo a continuación. Tenga en cuenta que se supone que el nombre de la variable del fichero cargado es <emphasis>userfile</emphasis>, tal como se define en el formulario anterior, pero puede ser cualquier nombre.
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><varname>$_FILES['userfile']['name']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
El nombre original del fichero, tal como en la máquina del cliente web.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$_FILES['userfile']['type']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
El tipo MIME del fichero, si el navegador ha proporcionado esta información. Por ejemplo, esto podría ser <literal>"image/gif"</literal>. Este tipo mime no es verificado por PHP y, por lo tanto, no se debe tomar su valor para sincronizarse.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$_FILES['userfile']['size']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
El tamaño, en bytes, del fichero cargado.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$_FILES['userfile']['tmp_name']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
El nombre temporal del fichero que será cargado en la máquina servidor.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$_FILES['userfile']['error']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
El <link linkend="features.file-upload.errors">código de error</link> asociado a la carga del fichero.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$_FILES['userfile']['full_path']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
La ruta completa tal como se envía por el navegador. Este valor no contiene siempre una verdadera jerarquía de carpetas, y no se debe confiar en él. Disponible a partir de PHP 8.1.0.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
<para>
|
|
El fichero cargado será almacenado temporalmente en el directorio temporal del sistema, a menos que se proporcione otro directorio con la directiva <link linkend="ini.upload-tmp-dir">upload_tmp_dir</link> del &php.ini;. El directorio por defecto del servidor puede ser cambiado en el entorno a través de la variable <envar>TMPDIR</envar>. Modificar el valor de esta variable con la función <function>putenv</function> en un script PHP será sin efecto. Esta variable de entorno también puede ser utilizada para asegurarse de que otras operaciones funcionen también en los ficheros cargados.
|
|
<example>
|
|
<title>Validación de carga de ficheros</title>
|
|
<para>
|
|
Véase también las funciones <function>is_uploaded_file</function> y <function>move_uploaded_file</function> para más información. El siguiente ejemplo cargará un fichero desde un formulario.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$uploaddir = '/var/www/uploads/';
|
|
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
|
|
|
|
echo '<pre>';
|
|
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
|
|
echo "El fichero es válido, y ha sido cargado con éxito. Aquí hay más información :\n";
|
|
} else {
|
|
echo "Ataque potencial por carga de ficheros. Aquí hay más información :\n";
|
|
}
|
|
|
|
echo 'Aquí hay algunas informaciones de depuración :';
|
|
print_r($_FILES);
|
|
|
|
echo '</pre>';
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
El script PHP que recibe el fichero cargado debe poder gestionar el fichero de manera apropiada. Se puede utilizar la variable <varname>$_FILES['userfile']['size']</varname> para recalar todos los ficheros que son demasiado grandes o demasiado pequeños. Se puede utilizar la variable <varname>$_FILES['userfile']['type']</varname> para descartar los ficheros que no tienen el tipo correcto, pero utilizarla únicamente para una serie de verificaciones, ya que este valor está completamente bajo el control del cliente y no es verificado por PHP. Se puede utilizar la información en <varname>$_FILES['userfile']['error']</varname> y adaptar su política en función de los <link linkend="features.file-upload.errors">códigos de error</link>. Sea cual sea su política, se debe borrar el fichero del directorio temporal o moverlo.
|
|
</simpara>
|
|
<simpara>
|
|
Si no se selecciona ningún fichero en el formulario, PHP devolverá <literal>0</literal> en <varname>$_FILES['userfile']['size']</varname> y nada en <varname>$_FILES['userfile']['tmp_name']</varname>.
|
|
</simpara>
|
|
<simpara>
|
|
El fichero será borrado automáticamente del directorio temporal al final del script, si no ha sido movido o renombrado.
|
|
</simpara>
|
|
<example>
|
|
<title>Envío de un array de ficheros</title>
|
|
<para>
|
|
PHP soporta los <link linkend="faq.html.arrays">arrays en HTML</link> así como con los ficheros.
|
|
</para>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<form action="" method="post" enctype="multipart/form-data">
|
|
<p>Imágenes:
|
|
<input type="file" name="pictures[]" />
|
|
<input type="file" name="pictures[]" />
|
|
<input type="file" name="pictures[]" />
|
|
<input type="submit" value="Enviar" />
|
|
</p>
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
foreach ($_FILES["pictures"]["error"] as $key => $error) {
|
|
if ($error == UPLOAD_ERR_OK) {
|
|
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
|
|
// basename() puede prevenir los ataques "filesystem traversal";
|
|
// otra validación/limpieza del nombre de fichero puede ser apropiada
|
|
$name = basename($_FILES["pictures"]["name"][$key]);
|
|
move_uploaded_file($tmp_name, "data/$name");
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
La barra de progreso de carga puede ser implementada utilizando <link linkend="session.upload-progress">la progresión de la carga a través de las sesiones</link>.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="features.file-upload.errors">
|
|
<title>Explicación sobre los mensajes de errores de carga de ficheros</title>
|
|
<simpara>
|
|
PHP devuelve un código de error apropiado en el array de ficheros. Este código de error es accesible en el índice <literal>['error']</literal> del array, que es creado durante la carga por PHP. En otras palabras, el mensaje de error es accesible en la variable <varname>$_FILES['userfile']['error']</varname>.
|
|
</simpara>
|
|
<simpara>
|
|
El valor de este código de error es una de las constantes <constant>UPLOAD_ERR_<replaceable>*</replaceable></constant>.
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="features.file-upload.common-pitfalls">
|
|
<title>Errores clásicos</title>
|
|
<simpara>
|
|
La variable <literal>MAX_FILE_SIZE</literal> no puede especificar un tamaño de fichero mayor que el tamaño que ha sido fijado por <link linkend="ini.upload-max-filesize">upload_max_filesize</link>, en el &php.ini;. El valor por defecto es 2 megaoctetos.
|
|
</simpara>
|
|
<simpara>
|
|
Si se activa un límite de memoria, puede ser necesario un valor mayor de <link linkend="ini.memory-limit">memory_limit</link>. Asegúrese de haber definido un valor para <link linkend="ini.memory-limit">memory_limit</link> lo suficientemente grande.
|
|
</simpara>
|
|
<simpara>
|
|
Si el valor de <link linkend="ini.max-execution-time">max_execution_time</link> es demasiado pequeño, el tiempo de ejecución del script puede exceder este valor. Asegúrese de haber definido un valor para <literal>max_execution_time</literal> lo suficientemente grande.
|
|
</simpara>
|
|
<note>
|
|
<simpara>
|
|
<link linkend="ini.max-execution-time">max_execution_time</link> afecta únicamente al tiempo de ejecución del script. El tiempo pasado en la actividad que aparece fuera de la ejecución del script como las llamadas al sistema con la función <function>system</function>, la función <function>sleep</function>, las consultas a las bases de datos, el tiempo empleado para realizar la carga del fichero, etc. no está incluido en el cálculo del tiempo máximo de ejecución del script.
|
|
</simpara>
|
|
</note>
|
|
<warning>
|
|
<simpara>
|
|
<link linkend="ini.max-input-time">max_input_time</link> define el tiempo máximo, en segundos, para que el script reciba los datos; esto incluye la carga del fichero. Para múltiples ficheros, o ficheros grandes, o incluso para usuarios en conexiones lentas, el valor por defecto de <literal>60</literal> segundos puede ser superado.
|
|
</simpara>
|
|
</warning>
|
|
<simpara>
|
|
Si <link linkend="ini.post-max-size">post_max_size</link> está definido de manera demasiado baja, los ficheros grandes no podrán ser cargados. Asegúrese de definir <literal>post_max_size</literal> con un tamaño suficiente.
|
|
</simpara>
|
|
<simpara>
|
|
La configuración de <link linkend="ini.max-file-uploads">max_file_uploads</link> controla el número máximo de ficheros que pueden ser enviados en una solicitud. Si el número de ficheros enviados supera este límite, entonces <varname>$_FILES</varname> dejará de recibir. Por ejemplo, si <link linkend="ini.max-file-uploads">max_file_uploads</link> vale <literal>10</literal>, entonces <varname>$_FILES</varname> nunca contendrá más de 10 entidades.
|
|
</simpara>
|
|
<simpara>
|
|
No validar los ficheros que se manipulan puede dar acceso a los usuarios a ficheros sensibles en otras carpetas.
|
|
</simpara>
|
|
<simpara>
|
|
Debido a la gran diversidad de sistemas, no se puede garantizar que los ficheros con nombres exóticos (por ejemplo, aquellos que contienen espacios) sean tratados correctamente.
|
|
</simpara>
|
|
<simpara>
|
|
El desarrollador no debe mezclar los campos <literal>input</literal> normales y los campos de carga en una misma variable (utilizando un nombre de <literal>input</literal> como <literal>foo[]</literal>).
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="features.file-upload.multiple">
|
|
<title>Cargar múltiples ficheros simultáneamente</title>
|
|
<simpara>
|
|
La carga de múltiples ficheros es posible utilizando diferentes nombres en el atributo <literal>name</literal> de la etiqueta <literal>input</literal>.
|
|
</simpara>
|
|
<simpara>
|
|
También es posible cargar múltiples ficheros simultáneamente y obtener la información en forma de array. Para ello, se debe utilizar la sintaxis de array en los nombres de las etiquetas HTML, como se ha hecho con las selecciones múltiples y las casillas de verificación.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Cargar múltiples ficheros simultáneamente</title>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<form action="file-upload.php" method="post" enctype="multipart/form-data">
|
|
Envíe múltiples ficheros: <br />
|
|
<input name="userfile[]" type="file" /><br />
|
|
<input name="userfile[]" type="file" /><br />
|
|
<input type="submit" value="Enviar los ficheros" />
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Cuando el formulario anterior ha sido enviado, los arrays <varname>$_FILES['userfile']</varname>, <varname>$_FILES['userfile']['name']</varname>, y <varname>$_FILES['userfile']['size']</varname> serán inicializados.
|
|
</simpara>
|
|
<simpara>
|
|
Por ejemplo, supongamos que los ficheros <filename>/home/test/review.html</filename> y <filename>/home/test/xwp.out</filename> han sido cargados. En este caso, <varname>$_FILES['userfile']['name'][0]</varname> contiene <filename>review.html</filename> y <varname>$_FILES['userfile']['name'][1]</varname> contiene <filename>xwp.out</filename>. De manera similar, <varname>$_FILES['userfile']['size'][0]</varname> contendrá el tamaño del fichero <filename>review.html</filename>, etc.
|
|
</simpara>
|
|
<simpara>
|
|
<varname>$_FILES['userfile']['name'][0]</varname>, <varname>$_FILES['userfile']['tmp_name'][0]</varname>, <varname>$_FILES['userfile']['size'][0]</varname> y <varname>$_FILES['userfile']['type'][0]</varname> también son creados.
|
|
</simpara>
|
|
<warning>
|
|
<simpara>
|
|
El parámetro <link linkend="ini.max-file-uploads">max_file_uploads</link> limita el número de ficheros que pueden ser enviados en una solicitud. Se debe verificar que su formulario no intente enviar más ficheros en la solicitud de lo que permite este límite.
|
|
</simpara>
|
|
</warning>
|
|
<para>
|
|
<example>
|
|
<title>Telever un directorio entero</title>
|
|
<simpara>
|
|
En los campos de televersión de fichero HTML, es posible televersar un directorio entero con el atributo <literal>webkitdirectory</literal>. Esta funcionalidad es soportada en la mayoría de los navegadores modernos.
|
|
</simpara>
|
|
<simpara>
|
|
Con la información <literal>full_path</literal>, es posible almacenar las rutas relativas o reconstruir la misma jerarquía de directorios en el directorio.
|
|
</simpara>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<form action="file-upload.php" method="post" enctype="multipart/form-data">
|
|
Envíe este directorio:<br />
|
|
<input name="userfile[]" type="file" webkitdirectory multiple />
|
|
<input type="submit" value="Enviar ficheros" />
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<warning>
|
|
<simpara>
|
|
El atributo <literal>webkitdirectory</literal> no es estándar y no está actualmente en proceso de estandarización. Esto no debe ser utilizado en sitios de producción orientados al Web: no funcionará para todos los usuarios. Puede haber grandes incompatibilidades entre las implementaciones y el comportamiento puede cambiar en el futuro.
|
|
</simpara>
|
|
<simpara>
|
|
PHP analiza únicamente la información de las rutas relativas enviadas por el navegador/user-agent y transmite la información en el array <varname>$_FILES</varname>. No hay garantías de que los valores en el array <literal>full_path</literal> contengan una verdadera estructura de directorios y la aplicación PHP no debe confiar en esta información.
|
|
</simpara>
|
|
</warning>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="features.file-upload.put-method">
|
|
<title>Carga por método PUT</title>
|
|
<para>
|
|
PHP soporta el método HTTP PUT utilizado por los navegadores para almacenar ficheros en un servidor. Las solicitudes de tipo PUT son mucho más simples que las cargas de ficheros utilizando el tipo POST, y se parecen a:
|
|
<example>
|
|
<title>Método PUT para las cargas de ficheros</title>
|
|
<programlisting role="HTTP">
|
|
<![CDATA[
|
|
PUT /path/filename.html HTTP/1.1
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Normalmente, esto significa que el servidor remoto guardará los datos que siguen en el fichero: <filename>/path/filename.html</filename> de su disco. Esto no es, por supuesto, muy seguro permitir que Apache o PHP sobrescriban cualquier fichero de la arborescencia. Para evitar esto, primero se debe indicar al servidor que se desea que un script PHP dado gestione la solicitud. Con Apache, hay una directiva para ello: <emphasis>Script</emphasis>. Puede ser colocada en cualquier lugar del fichero de configuración de Apache. En general, los webmasters la colocan en el bloque <literal><Directory></literal>, o tal vez en el bloque <literal><VirtualHost></literal>. La siguiente línea hará muy bien el trabajo:
|
|
<example>
|
|
<title>Directiva Apache para la carga por método PUT</title>
|
|
<programlisting>
|
|
<![CDATA[
|
|
Script PUT /put.php
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Indica a Apache que debe enviar las solicitudes de carga por método PUT al script <filename>put.php</filename>. Por supuesto, esto presupone que se ha activado PHP para que maneje los ficheros de tipo <filename class="extension">.php</filename>, y que PHP está activo. El recurso de destino para todas las solicitudes PUT de este script debe ser el script mismo, y no el nombre del fichero que el fichero cargado debe tener.
|
|
</simpara>
|
|
<simpara>
|
|
Con PHP, se querría hacer algo como lo siguiente en su put.php. Esto copiará el contenido del fichero cargado en el fichero <filename>myputfile.ext</filename> en el servidor. Probablemente se querrá realizar algunas verificaciones y/o identificar al usuario antes de realizar esta copia de fichero.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Guardado de ficheros HTTP PUT</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
/* Los datos PUT llegan del flujo */
|
|
$putdata = fopen("php://input", "r");
|
|
|
|
/* Abre un fichero para escritura */
|
|
$fp = fopen("myputfile.ext", "w");
|
|
|
|
/* Lectura de los datos, 1 Ko a la vez y escritura en el fichero */
|
|
while ($data = fread($putdata, 1024))
|
|
fwrite($fp, $data);
|
|
|
|
/* Cierre del flujo */
|
|
fclose($fp);
|
|
fclose($putdata);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="features.file-upload.errors.seealso">
|
|
&reftitle.seealso;
|
|
<para>
|
|
<simplelist>
|
|
<member><link linkend="security.filesystem">Seguridad de los ficheros</link></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
-->
|