mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-17 01:18:55 +00:00

git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@76370 c90b9560-bf6c-de11-be94-00142212c4b1
411 lines
15 KiB
XML
411 lines
15 KiB
XML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<!-- $Revision: 1.37 $ -->
|
|
<chapter id="features.file-upload">
|
|
<title>Handling file uploads</title>
|
|
|
|
<sect1 id="features.file-upload.post-method">
|
|
<title>POST method uploads</title>
|
|
|
|
<simpara>
|
|
PHP is capable of receiving file uploads from any RFC-1867
|
|
compliant browser (which includes Netscape Navigator 3 or later,
|
|
Microsoft Internet Explorer 3 with a patch from Microsoft, or
|
|
later without a patch). This feature lets people upload both text
|
|
and binary files. With PHP's authentication and file manipulation
|
|
functions, you have full control over who is allowed to upload and
|
|
what is to be done with the file once it has been uploaded.
|
|
</simpara>
|
|
<para>
|
|
Note that PHP also supports PUT-method file uploads as used by
|
|
Netscape Composer and W3C's Amaya clients. See the <link
|
|
linkend="features.file-upload.put-method">PUT Method
|
|
Support</link> for more details.
|
|
</para>
|
|
<para>
|
|
A file upload screen can be built by creating a special form which
|
|
looks something like this:
|
|
<example>
|
|
<title>File Upload Form</title>
|
|
<programlisting role="html">
|
|
<![CDATA[
|
|
<form enctype="multipart/form-data" action="_URL_" method="post">
|
|
<input type="hidden" name="MAX_FILE_SIZE" value="1000">
|
|
Send this file: <input name="userfile" type="file">
|
|
<input type="submit" value="Send File">
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
The _URL_ should point to a PHP file. The MAX_FILE_SIZE hidden
|
|
field must precede the file input field and its value is the
|
|
maximum filesize accepted. The value is in bytes.
|
|
<warning>
|
|
<para>
|
|
The MAX_FILE_SIZE is advisory to the browser. It is easy to
|
|
circumvent this maximum. So don't count on it that the browser
|
|
obeys you wish! The PHP-settings for maximum-size, however,
|
|
cannot be fooled.
|
|
</para>
|
|
</warning>
|
|
</para>
|
|
|
|
<para>
|
|
Variables defined for uploaded files differs depends on PHP
|
|
version and configuration. Following variables will be defined
|
|
within the destination script upon a successful upload. When <link
|
|
linkend="ini.track-vars">track_vars</link> is enabled,
|
|
$HTTP_POST_FILES/$_FILES array is initialized. Finally, related
|
|
variables may be initialized as globals when
|
|
<link linkend="ini.register-globals">register_globals</link>
|
|
is turned on. However, use of globals is not recommended anymore.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
<link linkend="ini.track-vars">track_vars</link> is always on
|
|
from PHP 4.0.3. From PHP 4.1.0 or later, $_FILES may be used
|
|
instead of
|
|
<varname>$HTTP_POST_FILES</varname>. <varname>$_FILES</varname> is
|
|
always global, so <literal>global</literal> should not be used
|
|
for $_FILES in function scope.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
<varname>$HTTP_POST_FILES</varname>/<varname>$_FILES</varname> is
|
|
provided to contain the uploaded file information.
|
|
</para>
|
|
|
|
<para>
|
|
The contents of <varname>$HTTP_POST_FILES</varname> are as
|
|
follows. Note that this assumes the use of the file upload name
|
|
'userfile', as used in the example script above:
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><varname>$HTTP_POST_FILES['userfile']['name']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
The original name of the file on the client machine.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$HTTP_POST_FILES['userfile']['type']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
The mime type of the file, if the browser provided this
|
|
information. An example would be
|
|
<literal>"image/gif"</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$HTTP_POST_FILES['userfile']['size']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
The size, in bytes, of the uploaded file.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><varname>$HTTP_POST_FILES['userfile']['tmp_name']</varname></term>
|
|
<listitem>
|
|
<para>
|
|
The temporary filename of the file in which the uploaded file
|
|
was stored on the server.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
<note>
|
|
<para>
|
|
PHP 4.1.0 or later supports a short track variable
|
|
<varname>$_FILES</varname>. PHP 3 does not support
|
|
<varname>$HTTP_POST_FILES</varname>.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
When <link linkend="ini.register-globals">register_globals</link>
|
|
is turned on in &php.ini; the available variables
|
|
are as follows. Note that the following variable names assume the
|
|
use of the file upload name 'userfile', as used in the example
|
|
script above:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>
|
|
<varname>$userfile</varname> - The temporary filename in which
|
|
the uploaded file was stored on the server machine.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<varname>$userfile_name</varname> - The original name or path
|
|
of the file on the sender's system.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<varname>$userfile_size</varname> - The size of the uploaded
|
|
file in bytes.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<varname>$userfile_type</varname> - The mime type of the file
|
|
if the browser provided this information. An example would be
|
|
"image/gif".
|
|
</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
Note that the "<varname>$userfile</varname>" part of the above
|
|
variables is whatever the name of the <input> field of
|
|
type="file" is in the upload form. In the above upload form
|
|
example, we chose to call it "userfile".
|
|
</para>
|
|
<note>
|
|
<para>
|
|
<literal>register_globals = On</literal> is not recommended for
|
|
security and performance reason.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
Files will by default be stored in the server's default temporary
|
|
directory, unless another location has been given with the <link
|
|
linkend="ini.upload-tmp-dir">upload_tmp_dir</link> directive in
|
|
&php.ini;. The server's default directory can
|
|
be changed by setting the environment variable
|
|
<envar>TMPDIR</envar> in the environment in which PHP runs.
|
|
Setting it using <function>putenv</function> from within a PHP
|
|
script will not work. This environment variable can also be used
|
|
to make sure that other operations are working on uploaded files,
|
|
as well.
|
|
<example>
|
|
<title>Validating file uploads</title>
|
|
<para>
|
|
The following examples are for versions of PHP 4 greater than
|
|
4.0.2. See the function entries for
|
|
<function>is_uploaded_file</function> and
|
|
<function>move_uploaded_file</function>.
|
|
</para>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// In PHP 4.1.0 or later, $_FILES should be used instead of $HTTP_POST_FILES.
|
|
if (is_uploaded_file($HTTP_POST_FILES['userfile']['tmp_name'])) {
|
|
copy($HTTP_POST_FILES['userfile']['tmp_name'], "/place/to/put/uploaded/file");
|
|
} else {
|
|
echo "Possible file upload attack. Filename: " . $HTTP_POST_FILES['userfile']['name'];
|
|
}
|
|
/* ...or... */
|
|
move_uploaded_file($HTTP_POST_FILES['userfile']['tmp_name'], "/place/to/put/uploaded/file");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
The PHP script which receives the uploaded file should implement
|
|
whatever logic is necessary for determining what should be done
|
|
with the uploaded file. You can for example use the
|
|
<varname>$HTTP_POST_FILES['userfile']['size']</varname> variable
|
|
to throw away any files that are either too small or too big. You
|
|
could use the
|
|
<varname>$HTTP_POST_FILES['userfile']['type']</varname> variable
|
|
to throw away any files that didn't match a certain type criteria.
|
|
Whatever the logic, you should either delete the file from the
|
|
temporary directory or move it elsewhere.
|
|
</simpara>
|
|
<simpara>
|
|
The file will be deleted from the temporary directory at the end
|
|
of the request if it has not been moved away or renamed.
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 id="features.file-upload.common-pitfalls">
|
|
<title>Common Pitfalls</title>
|
|
<simpara>
|
|
The <literal>MAX_FILE_SIZE</literal> item cannot specify a file size
|
|
greater than the file size that has been set in the <link
|
|
linkend="ini.upload-max-filesize">upload_max_filesize</link> ini-setting.
|
|
The default is 2 Megabytes.
|
|
</simpara>
|
|
<simpara>
|
|
If memory limit is enabled, larger <link
|
|
linkend="ini.memory-limit">memory_limit</link> may be needed. Make
|
|
sure to set <link linkend="ini.memory-limit">memory_limit</link>
|
|
large enough.
|
|
</simpara>
|
|
<!-- FIXME: max_execution_time INI -->
|
|
<simpara>
|
|
If <link linkend="ini.max-execution-time">max_execution_time</link>
|
|
is set too small, script execution may be exceeded the value. Make
|
|
sure to set <literal>max_execution_time</literal> large enough.
|
|
</simpara>
|
|
<simpara>
|
|
If <link linkend="ini.post-max-size">post_max_size</link> set too
|
|
small, large files cannot be uploaded. Make sure to set
|
|
<literal>post_max_size</literal> large enough.
|
|
</simpara>
|
|
<simpara>
|
|
Not validating which file you operate on may mean that users can access
|
|
sensitive information in other directories.
|
|
</simpara>
|
|
<simpara>
|
|
Please note that the CERN httpd seems to strip off everything
|
|
starting at the first whitespace in the content-type mime header
|
|
it gets from the client. As long as this is the case, CERN httpd
|
|
will not support the file upload feature.
|
|
</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 version 3.0.10.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
<example>
|
|
<title>Uploading multiple files</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="Send files">
|
|
</form>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
When the above form is submitted, the arrays
|
|
<varname>$HTTP_POST_FILES['userfile']</varname>,
|
|
<varname>$HTTP_POST_FILES['userfile']['name']</varname>, and
|
|
<varname>$HTTP_POST_FILES['userfile']['size']</varname> will be
|
|
initialized. (As well as in $_FILES for PHP 4.1.0 or
|
|
later. $HTTP_POST_VARS in PHP 3. When
|
|
<literal>register_globals</literal> is on, globals for uploaded
|
|
files are also initialized). Each of these will be a numerically
|
|
indexed array of the appropriate values for the submitted files.
|
|
</simpara>
|
|
<simpara>
|
|
For instance, assume that the filenames
|
|
<filename>/home/test/review.html</filename> and
|
|
<filename>/home/test/xwp.out</filename> are submitted. In this
|
|
case, <varname>$HTTP_POST_FILES['userfile']['name'][0]</varname>
|
|
would contain the value <filename>review.html</filename>, and
|
|
<varname>$HTTP_POST_FILES['userfile']['name'][1]</varname> would
|
|
contain the value <filename>xwp.out</filename>. Similarly,
|
|
<varname>$HTTP_POST_FILES['userfile']['size'][0]</varname> would
|
|
contain <filename>review.html</filename>'s filesize, and so forth.
|
|
</simpara>
|
|
<simpara>
|
|
<varname>$HTTP_POST_FILES['userfile']['name'][0]</varname>,
|
|
<varname>$HTTP_POST_FILES['userfile']['tmp_name'][0]</varname>,
|
|
<varname>$HTTP_POST_FILES['userfile']['size'][0]</varname>, and
|
|
<varname>$HTTP_POST_FILES['userfile']['type'][0]</varname> are
|
|
also set.
|
|
</simpara>
|
|
</sect1>
|
|
|
|
<sect1 id="features.file-upload.put-method">
|
|
<title>PUT method support</title>
|
|
|
|
<para>
|
|
PHP provides support for the HTTP PUT method used by clients such
|
|
as Netscape Composer and W3C Amaya. PUT requests are much simpler
|
|
than a file upload and they look something like this:
|
|
<informalexample>
|
|
<programlisting>
|
|
PUT /path/filename.html HTTP/1.1
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
This would normally mean that the remote client would like to save
|
|
the content that follows as: /path/filename.html in your web tree.
|
|
It is obviously not a good idea for Apache or PHP to automatically
|
|
let everybody overwrite any files in your web tree. So, to handle
|
|
such a request you have to first tell your web server that you
|
|
want a certain PHP script to handle the request. In Apache you do
|
|
this with the <emphasis>Script</emphasis> directive. It can be
|
|
placed almost anywhere in your Apache configuration file. A
|
|
common place is inside a <Directory> block or perhaps inside
|
|
a <Virtualhost> block. A line like this would do the trick:
|
|
<informalexample>
|
|
<programlisting>
|
|
Script PUT /put.php
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<simpara>
|
|
This tells Apache to send all PUT requests for URIs that match the
|
|
context in which you put this line to the put.php script. This
|
|
assumes, of course, that you have PHP enabled for the .php
|
|
extension and PHP is active.
|
|
</simpara>
|
|
<simpara>
|
|
Inside your put.php file you would then do something like this:
|
|
</simpara>
|
|
<para>
|
|
<informalexample><programlisting role="php">
|
|
<![CDATA[
|
|
<?php copy($PHP_UPLOADED_FILE_NAME,$DOCUMENT_ROOT.$REQUEST_URI); ?>
|
|
]]>
|
|
</programlisting></informalexample>
|
|
</para>
|
|
<simpara>
|
|
This would copy the file to the location requested by the remote
|
|
client. You would probably want to perform some checks and/or
|
|
authenticate the user before performing this file copy. The only
|
|
trick here is that when PHP sees a PUT-method request it stores
|
|
the uploaded file in a temporary file just like those handled but
|
|
the <link
|
|
linkend="features.file-upload.post-method">POST-method</link>.
|
|
When the request ends, this temporary file is deleted. So, your
|
|
PUT handling PHP script has to copy that file somewhere. The
|
|
filename of this temporary file is in the $PHP_PUT_FILENAME
|
|
variable, and you can see the suggested destination filename in
|
|
the $REQUEST_URI (may vary on non-Apache web servers). This
|
|
destination filename is the one that the remote client specified.
|
|
You do not have to listen to this client. You could, for example,
|
|
copy all uploaded files to a special uploads directory.
|
|
</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
|
|
-->
|