PHP Conference Japan 2024

上传多个文件

可以使用不同的 name 属性为 input 上传多个文件。

也可以同时上传多个文件,并自动将信息组织到数组中。为此,您需要在 HTML 表单中使用与多个选择和复选框相同的数组提交语法

示例 #1 上传多个文件

<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>

提交上述表单后,数组 $_FILES['userfile']$_FILES['userfile']['name']$_FILES['userfile']['size'] 将被初始化。

例如,假设提交了文件名 /home/test/review.html/home/test/xwp.out。在这种情况下,$_FILES['userfile']['name'][0] 将包含值 review.html,而 $_FILES['userfile']['name'][1] 将包含值 xwp.out。类似地,$_FILES['userfile']['size'][0] 将包含 review.html 的文件大小,依此类推。

$_FILES['userfile']['name'][0]$_FILES['userfile']['tmp_name'][0]$_FILES['userfile']['size'][0]$_FILES['userfile']['type'][0] 也已设置。

警告

max_file_uploads 配置设置限制了在一个请求中可以上传的文件数量。您需要确保您的表单在一个请求中尝试上传的文件数量不超过此限制。

示例 #2 上传整个目录

在 HTML 文件上传字段中,可以使用 webkitdirectory 属性上传整个目录。此功能在大多数现代浏览器中受支持。

使用 full_path 信息,可以存储相对路径,或在服务器上重建相同的目录。

<form action="file-upload.php" method="post" enctype="multipart/form-data">
  Send this directory:<br />
  <input name="userfile[]" type="file" webkitdirectory multiple />
  <input type="submit" value="Send files" />
</form>
警告

webkitdirectory 属性是非标准的,并且不在标准轨道上。不要在面向 Web 的生产站点上使用它:它不会对每个用户都起作用。实现之间也可能存在很大的不兼容性,并且行为将来可能会发生变化。

PHP 仅解析浏览器/用户代理提交的相对路径信息,并将该信息传递给 $_FILES 数组。不能保证 full_path 数组中的值包含真实的目录结构,并且 PHP 应用程序不得信任此信息。

添加注释

用户贡献的注释 8 条注释

phpuser at gmail dot com
19 年前
上传多个文件时,$_FILES 变量以以下形式创建

数组
(
[name] => 数组
(
[0] => foo.txt
[1] => bar.txt
)

[type] => 数组
(
[0] => text/plain
[1] => text/plain
)

[tmp_name] => 数组
(
[0] => /tmp/phpYzdqkD
[1] => /tmp/phpeEwEWG
)

[error] => 数组
(
[0] => 0
[1] => 0
)

[size] => 数组
(
[0] => 123
[1] => 456
)
)

我发现如果上传的文件数组采用以下形式,代码会更简洁一些

数组
(
[0] => 数组
(
[name] => foo.txt
[type] => text/plain
[tmp_name] => /tmp/phpYzdqkD
[error] => 0
[size] => 123
)

[1] => 数组
(
[name] => bar.txt
[type] => text/plain
[tmp_name] => /tmp/phpeEwEWG
[error] => 0
[size] => 456
)
)

我编写了一个快速函数,可以将 $_FILES 数组转换为更简洁(在我看来)的数组。

<?php

function reArrayFiles(&$file_post) {

$file_ary = array();
$file_count = count($file_post['name']);
$file_keys = array_keys($file_post);

for (
$i=0; $i<$file_count; $i++) {
foreach (
$file_keys as $key) {
$file_ary[$i][$key] = $file_post[$key][$i];
}
}

return
$file_ary;
}

?>

现在我可以执行以下操作

<?php

if ($_FILES['upload']) {
$file_ary = reArrayFiles($_FILES['ufile']);

foreach (
$file_ary as $file) {
print
'File Name: ' . $file['name'];
print
'File Type: ' . $file['type'];
print
'File Size: ' . $file['size'];
}
}

?>
i.g.e.o@ya (dot) ru
4 年前
对“phpuser at gmail dot com”14 年前的注释进行了一些更新。
此更新将传入的 _POST 文件信息转换为真正更友好的数组形式。
并且这些变体在非多文件上传和多文件上传中都表现相同
<?php
//函数重新格式化POST提交的文件数组
function reArrayFiles(&$file_post){
$isMulti = is_array($file_post['name']);
$file_count = $isMulti?count($file_post['name']):1;
$file_keys = array_keys($file_post);

$file_ary = []; //结果数组
for($i=0; $i<$file_count; $i++)
foreach(
$file_keys as $key)
if(
$isMulti)
$file_ary[$i][$key] = $file_post[$key][$i];
else
$file_ary[$i][$key] = $file_post[$key];

return
$file_ary;
}
?>
wizzard351 at yahoo dot com
10 年前
这也适用于 <input type=file multiple> 元素。

因此,如果您有如下 input 元素
<input type="file" multiple="multiple" name="foobar" />
应写成
<input type="file" multiple="multiple" name="foobar[]" />
否则,您只能获取其中一个文件。
steam dot bakyt2 at gmail dot com
1 年前
只需将临时路径与文件名组合起来,就会得到一个类似于以下的数组

array(2) {
["/tmp/phpAYCvcc"]=> string(10) "file1.jpg"
["/tmp/phpCDg79o"]=> string(10) "file2.jpg"
}

代码

$files = array_combine(
$_FILES['receipt']['tmp_name'],
$_FILES['receipt']['name']
);

foreach ($files as $key => $value) {
// 将文件保存到本地
}
Corey Ballou
14 年前
这是一个用于修复多维数组索引的函数,以便在处理文件上传时更容易解析。它接收一个单一的 $_FILES 字段数组作为参数,并根据数字键将每个上传的文件分开。这允许像这样迭代:

<?php
fixFilesArray
($_FILES['array_of_files']);
foreach (
$_FILES['array_of_files'] as $position => $file) {
// 应该输出带有索引 name、type、tmp_name、error、size 的数组
var_dump($file);
}
?>

代码如下:

<?php
/**
* 修复多个文件上传的奇特索引,从以下格式:
*
* $_FILES['field']['key']['index']
*
* 更改为更标准和合适的格式:
*
* $_FILES['field']['index']['key']
*
* @param array $files
* @author Corey Ballou
* @link http://www.jqueryin.com
*/
function fixFilesArray(&$files)
{
$names = array( 'name' => 1, 'type' => 1, 'tmp_name' => 1, 'error' => 1, 'size' => 1);

foreach (
$files as $key => $part) {
// 只处理有效的键和多个文件
$key = (string) $key;
if (isset(
$names[$key]) && is_array($part)) {
foreach (
$part as $position => $value) {
$files[$position][$key] = $value;
}
// 删除旧的键引用
unset($files[$key]);
}
}
}
?>
timspeelman at live dot nl
13 年前
重新排列 $_FILES 的最简洁方法

<?php
function rearrange( $arr ){
foreach(
$arr as $key => $all ){
foreach(
$all as $i => $val ){
$new[$i][$key] = $val;
}
}
return
$new;
}
?>
lookphp at gmail dot com
8 年前
这是一个非常简单的示例

第一部分:HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文档</title>
</head>
<body>
<form action="upload.php" method="post" multipart="" enctype="multipart/form-data">
<input type="file" name="img[]" multiple>
<input type="submit">
</form>
</body>
</html>

第二部分:PHP

<?php
echo '<pre>';
$img = $_FILES['img'];

if(!empty(
$img))
{
$img_desc = reArrayFiles($img);
print_r($img_desc);

foreach(
$img_desc as $val)
{
$newname = date('YmdHis',time()).mt_rand().'.jpg';
move_uploaded_file($val['tmp_name'],'./uploads/'.$newname);
}
}

function
reArrayFiles($file)
{
$file_ary = array();
$file_count = count($file['name']);
$file_key = array_keys($file);

for(
$i=0;$i<$file_count;$i++)
{
foreach(
$file_key as $val)
{
$file_ary[$i][$val] = $file[$val][$i];
}
}
return
$file_ary;
}
sabryabdelmohsen at gmail dot com
4 年前
function reArrayImages($file_post) {
$file_ary = [];
$file_keys = array_keys($file_post);
foreach ($file_post as $key => $value) {
foreach ($value as $key2 => $value2) {
$file_ary[$key2][$key] = $value2;
}
}
return $file_ary;
}
To Top