<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/features.file-upload.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'zh',
  ),
  'this' => 
  array (
    0 => 'features.file-upload.post-method.php',
    1 => 'POST 方法上传',
    2 => 'POST 方法上传',
  ),
  'up' => 
  array (
    0 => 'features.file-upload.php',
    1 => '文件上传处理',
  ),
  'prev' => 
  array (
    0 => 'features.file-upload.php',
    1 => '文件上传处理',
  ),
  'next' => 
  array (
    0 => 'features.file-upload.errors.php',
    1 => '错误信息说明',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'zh',
    'path' => 'features/file-upload.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="features.file-upload.post-method" class="sect1">
  <h2 class="title">POST 方法上传</h2>
  <p class="simpara">
   本特性可以使用户上传文本和二进制文件。用 PHP
   的认证和文件操作函数，可以完全控制允许哪些人上传以及文件上传后怎样处理。
  </p>
  <p class="simpara">
   PHP 能够接受任何来自符合 RFC-1867 标准的浏览器上传的文件。
  </p>

  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <strong>相关的设置</strong><br />
   <p class="para">
    请参阅 <var class="filename">php.ini</var> 的 <a href="ini.core.php#ini.file-uploads" class="link">file_uploads</a>，<a href="ini.core.php#ini.upload-max-filesize" class="link">upload_max_filesize</a>，<a href="ini.core.php#ini.upload-tmp-dir" class="link">upload_tmp_dir</a>，<a href="ini.core.php#ini.post-max-size" class="link">post_max_size</a>
    以及 <a href="info.configuration.php#ini.max-input-time" class="link">max_input_time</a> 设置选项。
   </p>
  </p></blockquote>

  <p class="para">
   请注意 PHP 也支持 PUT 方法的文件上传，<span class="productname">Netscape Composer</span>
   和 W3C 的 <span class="productname">Amaya</span> 客户端使用这种方法。请参阅<a href="features.file-upload.put-method.php" class="link">对 PUT 方法的支持</a>以获取更多信息。
  </p>
  <p class="para">
   <div class="example" id="example-1">
    <p><strong>示例 #1 文件上传表单</strong></p>
    <div class="example-contents"><p>
     可以如下建立一个特殊的表单来支持文件上传：
    </p></div>
    <div class="example-contents">
<div class="htmlcode"><pre class="htmlcode">&lt;!-- The data encoding type, enctype, MUST be specified as below --&gt;
&lt;form enctype=&quot;multipart/form-data&quot; action=&quot;__URL__&quot; method=&quot;POST&quot;&gt;
    &lt;!-- MAX_FILE_SIZE must precede the file input field --&gt;
    &lt;input type=&quot;hidden&quot; name=&quot;MAX_FILE_SIZE&quot; value=&quot;30000&quot; /&gt;
    &lt;!-- Name of input element determines name in $_FILES array --&gt;
    Send this file: &lt;input name=&quot;userfile&quot; type=&quot;file&quot; /&gt;
    &lt;input type=&quot;submit&quot; value=&quot;Send File&quot; /&gt;
&lt;/form&gt;</pre>
</div>
    </div>

    <div class="example-contents"><p>
     以上范例中的 <code class="literal">__URL__</code> 应该被换掉，指向一个真实的 PHP 文件。
    </p></div>
    <div class="example-contents"><p>
     <code class="literal">MAX_FILE_SIZE</code>
     隐藏字段（单位为字节）必须放在文件输入字段之前，其值为接收文件的最大尺寸。这是对浏览器的一个建议，PHP
     也会检查此项。在浏览器端可以简单绕过此设置，因此不要指望用此特性来阻挡大文件。实际上，PHP
     设置中的上传文件最大值是不会失效的。但是最好还是在表单中加上此项目，因为它可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。
    </p></div>
   </div>
  </p>

  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <p class="para">
    要确保文件上传表单的属性是
    <code class="literal">enctype=&quot;multipart/form-data&quot;</code>，否则文件上传不了。
   </p>
  </p></blockquote>

  <p class="para">
   全局变量 <var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES</a></var> 包含有所有上传的文件信息。
   数组的内容来自以下范例表单。我们假设文件上传字段的名称如下例所示，为
   <em>userfile</em>。名称可随意命名。
   <dl>
    
     <dt><var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['name']</a></var></dt>
     <dd>
      <p class="para">
       客户端机器文件的原名称。
      </p>
     </dd>
    
    
     <dt><var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['type']</a></var></dt>
     <dd>
      <p class="para">
       文件的 MIME 类型，如果浏览器提供此信息的话。一个例子是“<code class="literal">image/gif</code>”。不过此
       MIME 类型在 PHP 端并不检查，因此不要想当然认为有这个值。
       </p>
     </dd>
    
    
     <dt><var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['size']</a></var></dt>
     <dd>
      <p class="para">
       已上传文件的大小，单位为字节。
      </p>
     </dd>
    
    
     <dt><var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['tmp_name']</a></var></dt>
     <dd>
      <p class="para">
       文件被上传后在服务端储存的临时文件名。
      </p>
     </dd>
    
    
     <dt><var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['error']</a></var></dt>
     <dd>
      <p class="para">
       和该文件上传相关的<a href="features.file-upload.errors.php" class="link">错误代码</a>。
      </p>
     </dd>
    
    
     <dt><var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['full_path']</a></var></dt>
     <dd>
      <p class="para">
       浏览器提交的完整路径。该值并不总是包含真实的目录结构，因此不能被信任。从 PHP 8.1.0 起可用。
      </p>
     </dd>
    
   </dl>
  </p>

  <p class="para">
   文件被上传后，默认地会被储存到服务端的默认临时目录中，除非
   <var class="filename">php.ini</var> 中的 <a href="ini.core.php#ini.upload-tmp-dir" class="link">upload_tmp_dir</a>
   设置为其它的路径。服务端的默认临时目录可以通过更改 PHP
   运行环境的环境变量 <var class="envar">TMPDIR</var> 来重新设置，但是在
   PHP 脚本内部通过运行 <span class="function"><a href="function.putenv.php" class="function">putenv()</a></span>
   函数来设置是不起作用的。该环境变量也可以用来确认其它的操作也是在上传的文件上进行的。
   <div class="example" id="example-2">
    <p><strong>示例 #2 验证上传的文件</strong></p>
    <div class="example-contents"><p>
    请查阅函数 <span class="function"><a href="function.is-uploaded-file.php" class="function">is_uploaded_file()</a></span> 和
     <span class="function"><a href="function.move-uploaded-file.php" class="function">move_uploaded_file()</a></span> 以获取进一步的信息。
     以下范例处理由表单提供的文件上传。
    </p></div>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$uploaddir </span><span style="color: #007700">= </span><span style="color: #DD0000">'/var/www/uploads/'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$uploadfile </span><span style="color: #007700">= </span><span style="color: #0000BB">$uploaddir </span><span style="color: #007700">. </span><span style="color: #0000BB">basename</span><span style="color: #007700">(</span><span style="color: #0000BB">$_FILES</span><span style="color: #007700">[</span><span style="color: #DD0000">'userfile'</span><span style="color: #007700">][</span><span style="color: #DD0000">'name'</span><span style="color: #007700">]);<br /><br />echo </span><span style="color: #DD0000">'&lt;pre&gt;'</span><span style="color: #007700">;<br />if (</span><span style="color: #0000BB">move_uploaded_file</span><span style="color: #007700">(</span><span style="color: #0000BB">$_FILES</span><span style="color: #007700">[</span><span style="color: #DD0000">'userfile'</span><span style="color: #007700">][</span><span style="color: #DD0000">'tmp_name'</span><span style="color: #007700">], </span><span style="color: #0000BB">$uploadfile</span><span style="color: #007700">)) {<br />    echo </span><span style="color: #DD0000">"File is valid, and was successfully uploaded.\n"</span><span style="color: #007700">;<br />} else {<br />    echo </span><span style="color: #DD0000">"Possible file upload attack!\n"</span><span style="color: #007700">;<br />}<br /><br />echo </span><span style="color: #DD0000">'Here is some more debugging info:'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">print_r</span><span style="color: #007700">(</span><span style="color: #0000BB">$_FILES</span><span style="color: #007700">);<br /><br />print </span><span style="color: #DD0000">"&lt;/pre&gt;"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
  </p>
  <p class="simpara">
   接受上传文件的 PHP
   脚本为了决定接下来要对该文件进行哪些操作，应该实现任何逻辑上必要的检查。例如可以用
   <var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['size']</a></var>
   变量来排除过大或过小的文件，也可以通过
   <var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['type']</a></var>
   变量来排除文件类型和某种标准不相符合的文件，但只把这个当作一系列检查中的第一步，因为此值完全由客户端控制而在
   PHP 端并不检查。同时，还可以通过
   <var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['error']</a></var> 变量来根据不同的<a href="features.file-upload.errors.php" class="link">错误代码</a>来计划下一步如何处理。不管怎样，要么将该文件从临时目录中删除，要么将其移动到其它的地方。
  </p>
  <p class="simpara">
   如果表单中没有选择上传的文件，则 PHP 变量
   <var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['size']</a></var> 的值将为
   0，<var class="varname"><a href="reserved.variables.files.php" class="classname">$_FILES['userfile']['tmp_name']</a></var> 将为空。
  </p>
  <p class="simpara">
   如果该文件没有被移动到其它地方也没有被改名，则该文件将在表单请求结束时被删除。
  </p>

  <div class="example" id="example-3">
   <p><strong>示例 #3 上传一组文件</strong></p>
   <div class="example-contents"><p>
    PHP 的 <a href="faq.html.php#faq.html.arrays" class="link">HTML 数组特性</a>甚至支持文件类型。
   </p></div>
   <div class="example-contents">
<div class="htmlcode"><pre class="htmlcode">&lt;form action=&quot;&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
&lt;p&gt;Pictures:
&lt;input type=&quot;file&quot; name=&quot;pictures[]&quot; /&gt;
&lt;input type=&quot;file&quot; name=&quot;pictures[]&quot; /&gt;
&lt;input type=&quot;file&quot; name=&quot;pictures[]&quot; /&gt;
&lt;input type=&quot;submit&quot; value=&quot;Send&quot; /&gt;
&lt;/p&gt;
&lt;/form&gt;</pre>
</div>
   </div>

   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">foreach (</span><span style="color: #0000BB">$_FILES</span><span style="color: #007700">[</span><span style="color: #DD0000">"pictures"</span><span style="color: #007700">][</span><span style="color: #DD0000">"error"</span><span style="color: #007700">] as </span><span style="color: #0000BB">$key </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$error</span><span style="color: #007700">) {<br />    if (</span><span style="color: #0000BB">$error </span><span style="color: #007700">== </span><span style="color: #0000BB">UPLOAD_ERR_OK</span><span style="color: #007700">) {<br />        </span><span style="color: #0000BB">$tmp_name </span><span style="color: #007700">= </span><span style="color: #0000BB">$_FILES</span><span style="color: #007700">[</span><span style="color: #DD0000">"pictures"</span><span style="color: #007700">][</span><span style="color: #DD0000">"tmp_name"</span><span style="color: #007700">][</span><span style="color: #0000BB">$key</span><span style="color: #007700">];<br />        </span><span style="color: #FF8000">// basename() may prevent filesystem traversal attacks;<br />        // further validation/sanitation of the filename may be appropriate<br />        </span><span style="color: #0000BB">$name </span><span style="color: #007700">= </span><span style="color: #0000BB">basename</span><span style="color: #007700">(</span><span style="color: #0000BB">$_FILES</span><span style="color: #007700">[</span><span style="color: #DD0000">"pictures"</span><span style="color: #007700">][</span><span style="color: #DD0000">"name"</span><span style="color: #007700">][</span><span style="color: #0000BB">$key</span><span style="color: #007700">]);<br />        </span><span style="color: #0000BB">move_uploaded_file</span><span style="color: #007700">(</span><span style="color: #0000BB">$tmp_name</span><span style="color: #007700">, </span><span style="color: #DD0000">"data/</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">"</span><span style="color: #007700">);<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="para">
   文件上传进度条可以使用 <a href="session.upload-progress.php" class="link">Session Upload Progress</a> 来实现。
  </p>
 </div><?php manual_footer($setup); ?>