cvs: phpdoc-ca /features file-upload.xml
[email protected] ("Eduard Capell Brufau") Mon, 29 Aug 2005 19:08:05 -0000
| Newsgroups | php.doc.ca |
|---|---|
| Message-ID | <cvseduardcapell1125342485@cvsserver> |
--eduardcapell1125342485
Content-Type: text/plain
eduardcapell Mon Aug 29 15:08:05 2005 EDT
Added files:
/phpdoc-ca/features file-upload.xml
Log:
--eduardcapell1125342485
Content-Type: text/plain
Content-Disposition: attachment; filename="eduardcapell-20050829150805.txt"
http://cvs.php.net/co.php/phpdoc-ca/features/file-upload.xml?r=1.1&p=1
Index: phpdoc-ca/features/file-upload.xml
+++ phpdoc-ca/features/file-upload.xml
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Revision: 1.1 $ -->
<!-- EN-Revision: 1.86 Maintainer: eduardcapell Status: ready -->
<chapter id="features.file-upload">
<title>Gestió de les càrregues de fitxers</title>
<sect1 id="features.file-upload.post-method">
<title>Càrregues amb el mètode POST</title>
<simpara>
Aquesta característica permet que la gent carregui fitxers de text i
binaris. Amb les funcions de PHP d'autenticació i de manipulació de fitxers,
teniu un control complert sobre qui pot carregar fitxers i que se'n fa
d'aquests fitxers un cop s'han rebut al servidor.
</simpara>
<simpara>
El PHP pot rebre càrregues de fitxers des de qualsevol navegador que
compleixi amb l'estàndard RFC-1867 (això inclou
<productname>Netscape Navigator 3</productname> o superior,
<productname>Microsoft Internet Explorer 3</productname>
amb un pegat de Microsoft, o posteriors sense el pegat).
</simpara>
<note>
<title>Nota Relacionada amb Configuracions</title>
<para>
Vegeu també les directives
<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> and
<link linkend="ini.max-input-time">max_input_time</link>
a &php.ini;
</para>
</note>
<para>
El PHP també suporta càrregues amb el mètode PUT, tal com ho fan els
clients <productname>Netscape Composer</productname> i
<productname>Amaya de W3C</productname>. Vegeu el
<link linkend="features.file-upload.put-method">Suport del Mètode
PUT</link> per més detalls.
</para>
<para>
<example>
<title>Formulari de Càrrega de Fitxers</title>
<para>
Una pantalla de càrrega de fitxers es pot construir amb un formulari
especial que seria similar al següent:
</para>
<programlisting role="html">
<!-- The HTML comments in this example code are stripped.
This needs to be fixed in livedocs. -->
<![CDATA[
<!-- El tipus de codificació de les dades, enctype, HA DE SER especificat tal
com està a continuació. -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- MAX_FILE_SIZE ha de precedir el camp d'entrada -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- El nom de l'element d'entrada determina el nom al vector $_FILES -->
Enviar aquest fitxer: <input name="userfile" type="file" />
<input type="submit" value="Enviar" />
</form>
]]>
</programlisting>
<para>
El literal <literal>__URL__</literal> de l'exemple anterior hauria de ser
substituït, i hauria d'apuntar a un fitxer PHP.
</para>
<para>
El camp ocult, <literal>MAX_FILE_SIZE</literal> (expressat en octets) ha
de precedir el camp d'entrada del fitxer, i el seu valor serà el tamany
màxim acceptat pel fitxer. És un valor que el navegador pot comprovar, i
que PHP també comprova. És molt senzill d'enganyar els navegadors, i, per
tant, no us fieu d'aquesta característica. Els paràmetres del PHP per
maximum-size, en canvi, no poden ser enganyats. Aquest element del
formulari s'hauria d'utilitzar sempre , ja que mira d'evitar que els
usuaris passin per la molèstia d'esperar que un fitxer molt gran s'intenti
transferir, per acabar comprovant que era massa gran i la transferència
falla.
</para>
</example>
</para>
<note>
<para>
Assegureu-vos que el formulari de càrrega de fitxers té l'atribut
<literal>enctype="multipart/form-data"</literal>. Si no ho té, la càrrega
del fitxer no funcionarà.
</para>
</note>
<para>
La variable global <link linkend="reserved.variables.files">$_FILES</link>
existeix des de PHP 4.1.0 (Utilitzeu <varname>$HTTP_POST_FILES</varname> en
el seu lloc si és el cas que utilitzeu una versió anterior). Aquests vectors
contindran tota la informació sobre el fitxer carregat.
</para>
<para>
El continut del vector
<link linkend="reserved.variables.files">$_FILES</link> del formulari
d'exemple anterior seria de la manera que us mostrem a continuació. Se
suposa que el camp del formulari que contè el fitxer es diu
<emphasis>userfile</emphasis>, però podria ser qualsevol altre nom.
<variablelist>
<varlistentry>
<term><varname>$_FILES['userfile']['name']</varname></term>
<listitem>
<para>
El nom original del fitxer a la màquina client.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$_FILES['userfile']['type']</varname></term>
<listitem>
<para>
El tipus mime del fitxer, si el navegador ha enviat aquesta informació.
Un exemple seria <literal>"image/gif"</literal>. Aquest tipus mim, però,
no es comprova per part de PHP, i, per tant, no tingueu la seguretat que
aquest valor és del tot fiable.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$_FILES['userfile']['size']</varname></term>
<listitem>
<para>
La mida, en octets, del fitxe carregat.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$_FILES['userfile']['tmp_name']</varname></term>
<listitem>
<para>
El nom temporal del fitxer amb el qual ha estat guardat al servidor.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$_FILES['userfile']['error']</varname></term>
<listitem>
<para>
El <link linkend="features.file-upload.errors">codi d'error</link>
associat a aquesta càrrega. Aquest element es va afegir al PHP 4.2.0
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Els fitxers seran desats per defecte a la carpeta temporal del servidor, si
no és que s'ha especificat una altra ubicació a la directiva
<link linkend="ini.upload-tmp-dir">upload_tmp_dir</link> a &php.ini;.
La carpeta per defecte del servidor es pot canviar, establint la variable
d'entorn <envar>TMPDIR</envar> en l'entorn en que corri el PHP.
Establint-la amb la funció <function>putenv</function> des d'una seqüència
PHP no funcionarà. Aquesta variable d'entorn també es pot utilitzar per
assegurar-se que d'altres operacions funcionen en els fitxers carregats..
<example>
<title>Validació dels fitxers carregats</title>
<para>
Vegeu també les funcions <function>is_uploaded_file</function> i
<function>move_uploaded_file</function> per més informació. El següent
exemple processa el fitxer carregat que ens ha arribat des d'un formulari.
</para>
<programlisting role="php">
<![CDATA[
<?php
// En versions de PHP anteriors a 4.1.0, s'ha d'utilitar $HTTP_POST_FILES
// enlloc de $_FILES.
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "El fitxer és vàlid i s'ha carregat correctament..\n";
} else {
echo "Possible atac per càrrega de fitxer!\n";
}
echo 'Aquí teniu més informació de depuració:';
print_r($_FILES);
print "</pre>";
?>
]]>
</programlisting>
</example>
</para>
<simpara>
La seqüència PHP que rep el fitxer carregat ha d'implementar la lògica
necessària per tal de saber què cal fer amb el fitxer carregat. Potser
voldreu, per exemple, utilitzar la variable
<varname>$_FILES['userfile']['size']</varname> per descartar els fitxers que
són massa petits o massa grans. O bé podeu utilitzar la variable
<varname>$_FILES['userfile']['type']</varname> per a eliminar els fitxers
que no compleixein certs criteris, però utilitzeu-la només com una primera
part de la comprovació, perquè aquest valor està completament sota el
control del client i no es comprova per part de PHP. Des de PHP 4.2.0, podeu
utilitzar <varname>$_FILES['userfile']['error']</varname> i planificar la
vostra lògica en funció dels
<link linkend="features.file-upload.errors">codis d'error</link>.
En qualsevol cas, sigui quina sigui la lògica que empreu, sempre hauríeu
d'esborrar el fitxer de la carpeta temporal, o moure'l a una altra ubicació.
</simpara>
<simpara>
Si no s'ha seleccionat cap fitxer al formulari client, el PHP retornarà un
valor 0 per <varname>$_FILES['userfile']['size']</varname> i un valor buit
en <varname>$_FILES['userfile']['tmp_name']</varname>.
</simpara>
<simpara>
El fitxer s'esborrarà del directori temporal al final de la petició si no ha
estat renomenat o mogut.
</simpara>
<example>
<title>Càrrega d'un vector de fitxers</title>
<para>
El PHP suporta <link linkend="faq.html.arrays">vectors en HTML</link> fins
i tot amb els fitxers.
</para>
<programlisting role="html">
<![CDATA[
<form action="" method="post" enctype="multipart/form-data">
<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</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];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "data/$name");
}
}
?>
]]>
</programlisting>
</example>
</sect1>
<sect1 id="features.file-upload.errors">
<title>Explicació dels Missatges d'Error</title>
<simpara>
Des de PHP 4.2.0, el PHP retorna un codi d'error corresponent juntament amb
el vector del fitxer. El codi d'error el podem trobar al segment
<literal>error</literal> del vector que crea el PHP durant la càrrega del
fitxer. En altres paraules, l'error el podem trobar a
<varname>$_FILES['userfile']['error']</varname>.
</simpara>
<para>
<variablelist>
<varlistentry>
<term><constant>UPLOAD_ERR_OK</constant></term>
<listitem>
<para>
Valor: 0; No hi ha errors, el fitxer s'ha carregat amb èxit.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>UPLOAD_ERR_INI_SIZE</constant></term>
<listitem>
<para>
Valor: 1; El fitxer carregat excedeix la directiva
<link linkend="ini.upload-max-filesize">upload_max_filesize</link>
de &php.ini;.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>UPLOAD_ERR_FORM_SIZE</constant></term>
<listitem>
<para>
Valor: 2; El fitxer carregat excedeix el valor
<emphasis>MAX_FILE_SIZE</emphasis> que estava especificada al formulari
HTML.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>UPLOAD_ERR_PARTIAL</constant></term>
<listitem>
<para>
Valor: 3; El fitxer carregat només s'ha pogut carregar en part.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>UPLOAD_ERR_NO_FILE</constant></term>
<listitem>
<para>
Valor: 4; No s'ha carregat cap fitxer.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>UPLOAD_ERR_NO_TMP_DIR</constant></term>
<listitem>
<para>
Valor: 6; Falta una carpeta temporal. Això es va introduir al PHP 4.3.10
i al PHP 5.0.3.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><constant>UPLOAD_ERR_CANT_WRITE</constant></term>
<listitem>
<para>
Valor: 7; No s'ha pogut escriure al disc. Introduït al PHP 5.1.0.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<note>
<para>
Els noms previs van passar a ser constants a partir de 4.3.0.
</para>
</note>
</sect1>
<sect1 id="features.file-upload.common-pitfalls">
<title>Obstacles habituals</title>
<simpara>
L'ítem <literal>MAX_FILE_SIZE</literal> no pot establir un tamany de fitxer
superior al valor indicat pel paràmetre ini
<link linkend="ini.upload-max-filesize">upload_max_filesize</link>. El valor
per defecte és 2 Megabytes.
</simpara>
<simpara>
Si s'ha establert un límit de memòria, potser farà falta un valor superior
en la variable <link linkend="ini.memory-limit">memory_limit</link>.
Assegureu-vos que reserveu una quantitat suficient de memòria al valor de
<link linkend="ini.memory-limit">memory_limit</link>.
</simpara>
<simpara>
Si el valor de
<link linkend="ini.max-execution-time">max_execution_time</link> és massa
petit, l'execució de la seqüència pot ser superior al valor indicat.
Assegureu-vos que <literal>max_execution_time</literal> és prou gran.
</simpara>
<note>
<simpara>
<link linkend="ini.max-execution-time">max_execution_time</link> només
afecta el temps d'execució de la pròpia seqüència. Qualsevol temps passat
en activitat que té lloc fora de l'execució de la seqüència PHP, com ara
crides al sistema (funció <function>system</function>, funció
<function>sleep</function>, consultes a bases de dades, temps ocupat pel
processament de la càrrega de fitxers, etc. no s'inclouen en el temps
d'execució de la seqüència.
</simpara>
</note>
<warning>
<simpara>
<link linkend="ini.max-input-time">max_input_time</link> indica el màxim
temps, en segons, que la seqüència pot dedicar a rebre dades; això inclou
càrregues de fitxers. Per a fitxers grans, o fitxers múltiples, per a
usuaris amb connexions lentes, el valor per defecte de
<literal>60 seconds</literal> pot ser massa petit.
</simpara>
</warning>
<simpara>
Si <link linkend="ini.post-max-size">post_max_size</link> està establert a
un valor massa baix, no es podran carregar fitxers grans. Assegureu-vos que
el valor de <literal>post_max_size</literal> és prou gran.
</simpara>
<simpara>
Si no valideu el fitxer sobre el que treballeu, pot passar que els usuaris
puguin accedir a informació sensible en altres directoris.
</simpara>
<simpara>
Observeu que el <productname>CERN httpd</productname> sembla que elimina tot
el que ve a continuació del primer espai en blanc en la capçalera del tipus
de contingut mime. Mentre aquest sigui el cas,
<productname>CERN httpd</productname> no suportarà la característica de
càrrega de fitxers.
</simpara>
<simpara>
Degut a la gran quantitat d'estils de llistats de directoris, no podem
garantir que fitxers amb noms exòtics (per exemple, amb espais), es puguin
gestonar correctament.
</simpara>
<simpara>
El desenvolupador no pot barrejar camps d'entrada normals i camps de càrrega
de fitxers a la mateixa variable del formulari (utilitzant un nom de la
variable d'entrada com ara <literal>foo[]</literal>).
</simpara>
</sect1>
<sect1 id="features.file-upload.multiple">
<title>Uploading multiple files</title>
<simpara>
Multiple files can be uploaded using different
<literal>name</literal> for <literal>input</literal>.
</simpara>
<simpara>
It is also possible to upload multiple files simultaneously and
have the information organized automatically in arrays for you. To
do so, you need to use the same array submission syntax in the
HTML form as you do with multiple selects and checkboxes:
</simpara>
<note>
<para>
Support for multiple file uploads was added in PHP 3.0.10.
</para>
</note>
<para>
<example>
<title>Càrrega de fitxers múltiples</title>
<programlisting role="html">
<![CDATA[
<form action="file-upload.php" method="post" enctype="multipart/form-data">
Send these files:<br />
<input name="userfile[]" type="file" /><br />
<input name="userfile[]" type="file" /><br />
<input type="submit" value="Enviar els fitxers" />
</form>
]]>
</programlisting>
</example>
</para>
<simpara>
Quan s'envia el formulari anterior, els vectors
<varname>$_FILES['userfile']</varname>,
<varname>$_FILES['userfile']['name']</varname>, i
<varname>$_FILES['userfile']['size']</varname> s'inicialitzaran (igual que
la variable <varname>$HTTP_POST_FILES</varname> per versions de PHP
anteriors a 4.1.0).
Quan <link linkend="ini.register-globals">register_globals</link> està
activada, les variables globals pels fitxers carregats també s'inicialitzen.
Cada una d'aquestes serà un vector indexat numèricament, que contindrà els
valors apropiats pels fitxers enviats.
</simpara>
<simpara>
Per exemple, imagineu que hem rebut els fitxers amb els noms
<filename>/home/test/review.html</filename> i
<filename>/home/test/xwp.out</filename>. En aquest cas,
<varname>$_FILES['userfile']['name'][0]</varname> contindria el valor
<filename>review.html</filename>, i
<varname>$_FILES['userfile']['name'][1]</varname> contindria el valor
<filename>xwp.out</filename>. De manera semblant,
<varname>$_FILES['userfile']['size'][0]</varname> contindria el tamany de
<filename>review.html</filename> i així successivament.
</simpara>
<simpara>
<varname>$_FILES['userfile']['name'][0]</varname>,
<varname>$_FILES['userfile']['tmp_name'][0]</varname>,
<varname>$_FILES['userfile']['size'][0]</varname>, i
<varname>$_FILES['userfile']['type'][0]</varname> també tindran valors·
</simpara>
</sect1>
<sect1 id="features.file-upload.put-method">
<title>Suport del mètode PUT</title>
<simpara>
El suport del mètode PUT ha canviat entre les versions PHP 3 i PHP 4.
A PHP 4, s'ha d'utilitzar el flux de dades d'entrada estàndard, per tal de
llegir el contingut d'un HTTP PUT.
</simpara>
<para>
<example>
<title>Guardar fitxers amb HTTP PUT en PHP 4</title>
<programlisting role="php">
<![CDATA[
<?php
/* Les dades PUT arriben en el flux stdin */
$putdata = fopen("php://stdin", "r");
/* Obrim un fitxer per escriptura */
$fp = fopen("myputfile.ext", "w");
/* Llegim les dades, 1KB cada cop, i les anem escrivint */
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* Tanquem els fluxes de dades */
fclose($fp);
fclose($putdata);
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Tota la documentació següent fa referència exclusivament a PHP 3.
</para>
</note>
<para>
El PHP dóna suport al mètode HTTP PUT que és utilitzat per clients com
<productname>Netscape Composer</productname> i
<productname>W3C Amaya</productname>. Les peticions PUT són molt més simples
que una càrrega de fitxer, i són semblants a:
<informalexample>
<programlisting role="HTTP">
<![CDATA[
PUT /path/filename.html HTTP/1.1
]]>
</programlisting>
</informalexample>
</para>
<para>
Normalment això significaria que el client remot indicari el nom (amb la
ruta complerta) amb el qual s'hauria de guardar el fitxer al servidor, de la
manera següent: <filename>/path/filename.html</filename>, relatiu a l'arrel
del servidor web. És evident que no és una bona idea que l'Apache o el PHP
deixin de forma automàtica que qualsevol sobreescrigui qualsevol fitxer del
servdidor web. Per tant, per a gestionar una petició així, primer se li ha
de dir al servidor web que es vol que una seqüència PHP gestioni la petició.
En Apache, això es fa amb la directiva <emphasis>Script</emphasis>. Es pot
posar aquesta directiva pràcticament a qualsevol lloc del fitxer de
configuració de l'Apache. Un lloc habitual és dins d'un bloc
<Directory> o bé <Virtualhost> block. La línia seria així:
<informalexample>
<programlisting>
<![CDATA[
Script PUT /put.php
]]>
</programlisting>
</informalexample>
</para>
<simpara>
Això li diria a l'Apache que totes les peticions PUT que s'ajustin al
context en què posem aquesta línia es transferiran a la seqüència put.php.
Això suposa, evidentment, que hem habilitat el PHP per l'extensió .php i que
el PHP està actiu.
</simpara>
<simpara>
Dins del vostre fitxer put.php hi posaríem alguna cosa com això:
</simpara>
<para>
<informalexample><programlisting role="php">
<![CDATA[
<?php copy($PHP_UPLOADED_FILE_NAME, $DOCUMENT_ROOT . $REQUEST_URI); ?>
]]>
</programlisting></informalexample>
</para>
<simpara>
Això copiaria el fitxer a la ubicació sol·licitada pel client. Probablement
voldríem fer alguna operació de control i/o autenticació de l'usuari abans
de fer la còpia del fitxer. L'únic truc especial aquí és el fet que quan el
PHP veu una petició PUT, guarda el fitxer en una ubicació temporal, de la
mateixa manera que les peticions amb el
<link linkend="features.file-upload.post-method">mètode POST</link>.
Quan finalitza la petició, el fitxer temporal s'esborrarà. Per tan, la
seqüència que gestiona la petició PUT ha de copiar el fitxer a algun altre
lloc. El nom del fitxer temporal és a la variable
<varname>$PHP_PUT_FILENAME</varname> i podeu veure la destinació suggerida
la variable <varname>$REQUEST_URI</varname> (aquest nom pot ser diferent en
servidors web no Apache). Aquest fitxer de destinació és el que el client ha
indicat, i no necessàriament li hem de fer cas. Podríem, per exemple, copiar
tots els fitxers carregats a una ubicació especial de càrregues de fitxers
dels clients.
</simpara>
</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:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
--eduardcapell1125342485--