<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >文件上传处理</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="PHP 手册" HREF="index.html"><LINK REL="UP" TITLE="特点" HREF="features.html"><LINK REL="PREVIOUS" TITLE="处理 XForms" HREF="features.xforms.html"><LINK REL="NEXT" TITLE="错误信息说明" HREF="features.file-upload.errors.html"><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8"></HEAD ><BODY CLASS="chapter" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >PHP 手册</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="features.xforms.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" ></TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="features.file-upload.errors.html" ACCESSKEY="N" >下一页</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="chapter" ><H1 ><A NAME="features.file-upload" >章 38. 文件上传处理</A ></H1 ><DIV CLASS="TOC" ><DL ><DT ><B >目录</B ></DT ><DT ><A HREF="features.file-upload.html#features.file-upload.post-method" >POST 方法上传</A ></DT ><DT ><A HREF="features.file-upload.errors.html" >错误信息说明</A ></DT ><DT ><A HREF="features.file-upload.common-pitfalls.html" >常见缺陷</A ></DT ><DT ><A HREF="features.file-upload.multiple.html" >上传多个文件</A ></DT ><DT ><A HREF="features.file-upload.put-method.html" >对 PUT 方法的支持</A ></DT ></DL ></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="features.file-upload.post-method" >POST 方法上传</A ></H1 ><P > 本特性可以使用户上传文本和二进制文件。用 PHP 的认证和文件操作函数,可以完全控制允许哪些人上传以及文件上传后怎样处理。 </P ><P > PHP 能够接受任何来自符合 RFC-1867 标准的浏览器(包括 <SPAN CLASS="productname" >Netscape Navigator 3</SPAN > 及更高版本,打了补丁的 <SPAN CLASS="productname" >Microsoft Internet Explorer 3</SPAN > 或者更高版本)上传的文件。 </P ><DIV CLASS="note" ><BLOCKQUOTE CLASS="note" ><P ><B >相关的设置: </B > 请参阅 <TT CLASS="filename" >php.ini</TT > 的 <A HREF="ini.core.html#ini.file-uploads" >file_uploads</A >,<A HREF="ini.core.html#ini.upload-max-filesize" >upload_max_filesize</A >,<A HREF="ini.core.html#ini.upload-tmp-dir" >upload_tmp_dir</A ><A HREF="ini.core.html#ini.post-max-size" >post_max_size</A > 以及 <A HREF="ref.info.html#ini.max-input-time" >max_input_time</A > 设置选项。 </P ></BLOCKQUOTE ></DIV ><P > 请注意 PHP 也支持 PUT 方法的文件上传,<SPAN CLASS="productname" >Netscape Composer</SPAN > 和 W3C 的 <SPAN CLASS="productname" >Amaya</SPAN > 客户端使用这种方法。请参阅<A HREF="features.file-upload.put-method.html" >对 PUT 方法的支持</A >以获取更多信息。 </P ><P > <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN7032" ></A ><P ><B >例 38-1. 文件上传表单</B ></P ><P > 可以如下建立一个特殊的表单来支持文件上传: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="html" ><!-- The data encoding type, enctype, MUST be specified as below --> <form enctype="multipart/form-data" action="__URL__" method="POST"> <!-- MAX_FILE_SIZE must precede the file input field --> <input type="hidden" name="MAX_FILE_SIZE" value="30000" /> <!-- Name of input element determines name in $_FILES array --> Send this file: <input name="userfile" type="file" /> <input type="submit" value="Send File" /> </form></PRE ></TD ></TR ></TABLE ><P > 以上范例中的 <TT CLASS="literal" >__URL__</TT > 应该被换掉,指向一个真实的 PHP 文件。 </P ><P > <TT CLASS="literal" >MAX_FILE_SIZE</TT > 隐藏字段(单位为字节)必须放在文件输入字段之前,其值为接收文件的最大尺寸。这是对浏览器的一个建议,PHP 也会检查此项。在浏览器端可以简单绕过此设置,因此不要指望用此特性来阻挡大文件。实际上,PHP 设置中的上传文件最大值是不会失效的。但是最好还是在表单中加上此项目,因为它可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。 </P ></DIV ></TD ></TR ></TABLE > </P ><DIV CLASS="note" ><BLOCKQUOTE CLASS="note" ><P ><B >注意: </B > 要确保文件上传表单的属性是 <TT CLASS="literal" >enctype="multipart/form-data"</TT >,否则文件上传不了。 </P ></BLOCKQUOTE ></DIV ><P > 全局变量 <A HREF="reserved.variables.html#reserved.variables.files" >$_FILES</A > 自 PHP 4.1.0 起存在(在更早的版本中用 <CODE CLASS="varname" >$HTTP_POST_FILES</CODE > 替代)。此数组包含有所有上传的文件信息。 </P ><P > 以上范例中 <A HREF="reserved.variables.html#reserved.variables.files" >$_FILES</A > 数组的内容如下所示。我们假设文件上传字段的名称如上例所示,为 <SPAN CLASS="emphasis" ><I CLASS="emphasis" >userfile</I ></SPAN >。名称可随意命名。 <P ></P ><DIV CLASS="variablelist" ><DL ><DT ><CODE CLASS="varname" >$_FILES['userfile']['name']</CODE ></DT ><DD ><P > 客户端机器文件的原名称。 </P ></DD ><DT ><CODE CLASS="varname" >$_FILES['userfile']['type']</CODE ></DT ><DD ><P > 文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是“<TT CLASS="literal" >image/gif</TT >”。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。 </P ></DD ><DT ><CODE CLASS="varname" >$_FILES['userfile']['size']</CODE ></DT ><DD ><P > 已上传文件的大小,单位为字节。 </P ></DD ><DT ><CODE CLASS="varname" >$_FILES['userfile']['tmp_name']</CODE ></DT ><DD ><P > 文件被上传后在服务端储存的临时文件名。 </P ></DD ><DT ><CODE CLASS="varname" >$_FILES['userfile']['error']</CODE ></DT ><DD ><P > 和该文件上传相关的<A HREF="features.file-upload.errors.html" >错误代码</A >。此项目是在 PHP 4.2.0 版本中增加的。 </P ></DD ></DL ></DIV > </P ><P > 文件被上传后,默认地会被储存到服务端的默认临时目录中,除非 <TT CLASS="filename" >php.ini</TT > 中的 <A HREF="ini.core.html#ini.upload-tmp-dir" >upload_tmp_dir</A > 设置为其它的路径。服务端的默认临时目录可以通过更改 PHP 运行环境的环境变量 <CODE CLASS="envar" >TMPDIR</CODE > 来重新设置,但是在 PHP 脚本内部通过运行 <A HREF="function.putenv.html" ><B CLASS="function" >putenv()</B ></A > 函数来设置是不起作用的。该环境变量也可以用来确认其它的操作也是在上传的文件上进行的。 <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN7082" ></A ><P ><B >例 38-2. 使文件上传生效</B ></P ><P > 请查阅函数 <A HREF="function.is-uploaded-file.html" ><B CLASS="function" >is_uploaded_file()</B ></A > 和 <A HREF="function.move-uploaded-file.html" ><B CLASS="function" >move_uploaded_file()</B ></A > 以获取进一步的信息。以下范例处理由表单提供的文件上传。 </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#FF8000">// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead<br />// of $_FILES.<br /><br /></font><font color="#0000BB">$uploaddir </font><font color="#007700">= </font><font color="#DD0000">'/var/www/uploads/'</font><font color="#007700">;<br /></font><font color="#0000BB">$uploadfile </font><font color="#007700">= </font><font color="#0000BB">$uploaddir </font><font color="#007700">. </font><font color="#0000BB">basename</font><font color="#007700">(</font><font color="#0000BB">$_FILES</font><font color="#007700">[</font><font color="#DD0000">'userfile'</font><font color="#007700">][</font><font color="#DD0000">'name'</font><font color="#007700">]);<br /><br />echo </font><font color="#DD0000">'<pre>'</font><font color="#007700">;<br />if (</font><font color="#0000BB">move_uploaded_file</font><font color="#007700">(</font><font color="#0000BB">$_FILES</font><font color="#007700">[</font><font color="#DD0000">'userfile'</font><font color="#007700">][</font><font color="#DD0000">'tmp_name'</font><font color="#007700">], </font><font color="#0000BB">$uploadfile</font><font color="#007700">)) {<br /> echo </font><font color="#DD0000">"File is valid, and was successfully uploaded.\n"</font><font color="#007700">;<br />} else {<br /> echo </font><font color="#DD0000">"Possible file upload attack!\n"</font><font color="#007700">;<br />}<br /><br />echo </font><font color="#DD0000">'Here is some more debugging info:'</font><font color="#007700">;<br /></font><font color="#0000BB">print_r</font><font color="#007700">(</font><font color="#0000BB">$_FILES</font><font color="#007700">);<br /><br />print </font><font color="#DD0000">"</pre>"</font><font color="#007700">;<br /><br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE > </P ><P > 接受上传文件的 PHP 脚本为了决定接下来要对该文件进行哪些操作,应该实现任何逻辑上必要的检查。例如可以用 <CODE CLASS="varname" >$_FILES['userfile']['size']</CODE > 变量来排除过大或过小的文件,也可以通过 <CODE CLASS="varname" >$_FILES['userfile']['type']</CODE > 变量来排除文件类型和某种标准不相符合的文件,但只把这个当作一系列检查中的第一步,因为此值完全由客户端控制而在 PHP 端并不检查。自 PHP 4.2.0 起,还可以通过 <CODE CLASS="varname" >$_FILES['userfile']['error']</CODE > 变量来根据不同的<A HREF="features.file-upload.errors.html" >错误代码</A >来计划下一步如何处理。不管怎样,要么将该文件从临时目录中删除,要么将其移动到其它的地方。 </P ><P > 如果表单中没有选择上传的文件,则 PHP 变量 <CODE CLASS="varname" >$_FILES['userfile']['size']</CODE > 的值将为 0,<CODE CLASS="varname" >$_FILES['userfile']['tmp_name']</CODE > 将为空。 </P ><P > 如果该文件没有被移动到其它地方也没有被改名,则该文件将在表单请求结束时被删除。 </P ><TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="AEN7097" ></A ><P ><B >例 38-3. 上传一组文件</B ></P ><P > PHP 的 <A HREF="faq.html.html#faq.html.arrays" >HTML 数组特性</A >甚至支持文件类型。 </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="html" ><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></PRE ></TD ></TR ></TABLE ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><code><font color="#000000"> <font color="#0000BB"><?php<br /></font><font color="#007700">foreach (</font><font color="#0000BB">$_FILES</font><font color="#007700">[</font><font color="#DD0000">"pictures"</font><font color="#007700">][</font><font color="#DD0000">"error"</font><font color="#007700">] as </font><font color="#0000BB">$key </font><font color="#007700">=> </font><font color="#0000BB">$error</font><font color="#007700">) {<br /> if (</font><font color="#0000BB">$error </font><font color="#007700">== </font><font color="#0000BB">UPLOAD_ERR_OK</font><font color="#007700">) {<br /> </font><font color="#0000BB">$tmp_name </font><font color="#007700">= </font><font color="#0000BB">$_FILES</font><font color="#007700">[</font><font color="#DD0000">"pictures"</font><font color="#007700">][</font><font color="#DD0000">"tmp_name"</font><font color="#007700">][</font><font color="#0000BB">$key</font><font color="#007700">];<br /> </font><font color="#0000BB">$name </font><font color="#007700">= </font><font color="#0000BB">$_FILES</font><font color="#007700">[</font><font color="#DD0000">"pictures"</font><font color="#007700">][</font><font color="#DD0000">"name"</font><font color="#007700">][</font><font color="#0000BB">$key</font><font color="#007700">];<br /> </font><font color="#0000BB">move_uploaded_file</font><font color="#007700">(</font><font color="#0000BB">$tmp_name</font><font color="#007700">, </font><font color="#DD0000">"data/$name"</font><font color="#007700">);<br /> }<br />}<br /></font><font color="#0000BB">?></font> </font> </code></TD ></TR ></TABLE ></DIV ></TD ></TR ></TABLE ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="features.xforms.html" ACCESSKEY="P" >上一页</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >起始页</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="features.file-upload.errors.html" ACCESSKEY="N" >下一页</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >处理 XForms</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="features.html" ACCESSKEY="U" >上一级</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >错误信息说明</TD ></TR ></TABLE ></DIV ></BODY ></HTML >