上传多个文件

可以使用不同的 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 应用程序不应信任此信息。

添加备注

用户贡献的备注 19 备注

354
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'];
}
}

?>
17
i.g.e.o@ya (dot) ru
4 年前
对 14 年前 "phpuser at gmail dot com" 的备注进行了一些更新。
该更新将传入的 _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;
}
?>
2
steam dot bakyt2 at gmail dot com
9 个月前
只需将临时路径与文件名合并,就会得到一个类似于以下的数组:

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) {
// 将文件保存到本地
}
51
wizzard351 at yahoo dot com
10 年前
对于 <input type=file multiple> 元素来说,这也是必需的。

因此,如果你有一个这样的输入元素
<input type="file" multiple="multiple" name="foobar" />
应写成
<input type="file" multiple="multiple" name="foobar[]" />
否则,你将只能获取其中一个文件。
12
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]);
}
}
}
?>
15
timspeelman at live dot nl
12 年前
重新排列 $_FILES 的最干净方法

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

第一部分:HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</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;
}
0
sabryabdelmohsen at gmail dot com
3 年前
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;
}
-5
jess at semlabs dot co dot uk
15 年前
如果你尝试使用多维名称上传文件,例如:

<input type="file" name="submission[screenshot]" />
<input type="file" name="other[dem][][img][]" />

你会得到一个意想不到的格式,例如:

<?php
array(
'submission' => array
(
'name' => array( 'screenshot' => 'monster_wallpaper.jpg' ),
'type' => array( 'screenshot' => 'image/jpeg' ),
'tmp_name' => array( 'screenshot' => '/tmp/php48lX2Y' ),
'error' => array( 'screenshot' => 0 ),
'size' => array( 'screenshot' => 223262 ),
),
....
?>

可以使用以下函数递归地将数组重新格式化为通常的格式

<?php
function format_files_array( $files, $name = null, &$new = false, $path = false ){
$names = array( 'name' => 'name', 'type' => 'type', 'tmp_name' => 'tmp_name', 'error' => 'error', 'size' => 'size' );

foreach(
$files as $key => &$part )
{
$key = ( string ) $key;
if(
in_array( $key, $names ) )
$name = $key;
if( !
in_array( $key, $names ) )
$path[] = $key;
if(
is_array( $part ) )
$part = format_files_array( $part, $name, $new, $path );
elseif( !
is_array( $part ) )
{
$current =& $new;
foreach(
$path as $p )
$current =& $current[$p];
$current[$name] = $part;
unset(
$path );
$name = null;
}
}

return
$new;
}
?>
-6
swayalex at gmail dot com
8 年前
递归解决方案,用于复杂的情况(支持任何嵌套数组,包括索引数组)

function getFixedFilesArray() {
$walker = function ($arr, $fileInfokey, callable $walker) {
$ret = array();
foreach ($arr as $k => $v) {
if (is_array($v)) {
$ret[$k] = $walker($v, $fileInfokey, $walker);
} else {
$ret[$k][$fileInfokey] = $v;
}
}
return $ret;
};

$files = array();
foreach ($_FILES as $name => $values) {
// 初始化用于 array_merge
if (!isset($files[$name])) {
$files[$name] = array();
}
if (!is_array($values['error'])) {
// 正常语法
$files[$name] = $values;
} else {
// html 数组特性
foreach ($values as $fileInfoKey => $subArray) {
$files[$name] = array_replace_recursive($files[$name], $walker($subArray, $fileInfoKey, $walker));
}
}
}

return $files;
}
-5
Eric
8 年前
这只是对 "phpuser" 在此提供的顶层注释中代码的修改。他的/她的版本要求传递给函数的 $file_post 数组是由带有 multiple 属性的表单提交创建的。在 html 输入标签中设置了 multiple 属性后,无论发送一个文件还是多个文件,$_FILES["fileInputName"]["name"] 都是一个数组。但是,当 <input type="file"> 在没有 multiple 属性的情况下使用时,$_FILES["fileInputName"]["name"] 不是一个数组,它包含一个包含文件名字符串的数组。为了使用这个整洁的函数,无论是否设置了 multiple 属性,以及为了获得一个你可以在两种情况下进行 "foreach" 迭代的数组,请使用这个修改后的代码

function reArrayFiles(&$file_post)
{
$file_ary = array();
$multiple = is_array($file_post['name']);

$file_count = $multiple ? count($file_post['name']) : 1;
$file_keys = array_keys($file_post);

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

return $file_ary;
}
-8
hotmail.com[at]notdefix
16 年前
使用多个文件上传

post_max_size: 客户端发布的总数据量(所有文件和所有其他表单字段)

upload_max_filesize: 单个文件的最大大小。(就像 <input type="hidden" name="MAX_FILE_SIZE" value="..."/>)

所以,使用以下指令
post_max_size 25M
upload_max_filesize 2M

你可以发送 12 个大小不超过 2 MB 的文件,并为你的额外表单值使用最多 1 MB 的空间。

只要你只将单个文件副本读入内存,memory_limit 指令也可以保持合理的小。
-12
contato at dgmike dot com dot br
13 年前
我更喜欢这样!

<?php
public function arrayImages ( &$file_post )
{
if( empty(
$file_post ) ) {
return
$file_post;
}
if(
'array'!==gettype($file_post['name']) ) {
return
$file_post;
}
$keys = array_keys($file_post['name']);
$file_array = array();
foreach (
$keys as $key) {
foreach (
$file_post as $res=>$item) {
$file_array[$key][$res] = $item[$key];
}
}
return
$file_array;
}
?>
-10
jefrey no spam please at jefrey dot ml
8 年前
有一次,我不得不维护一个庞大的 ERP 系统,其中在一个数组内包含多个多个上传输入。就像这样

<form method="post" enctype="multipart/form-data">
<input type="file" multiple name="upload[avatar]" />
<input type="file" multiple name="upload[attachment]" />
<input type="file" multiple name="upload2[avatar]" />
<input type="file" multiple name="upload2[attachment]" />
<input type="submit" />
</form>

$_FILES 数组的创建方式如下

数组
(
[upload] => Array
(
[name] => 数组
(
[avatar] => teste.c
[attachment] => teste
)

[type] => 数组
(
[avatar] => text/x-csrc
[attachment] => application/octet-stream
)

[tmp_name] => 数组
(
[avatar] => /opt/lampp/temp/phpuf3KNj
[attachment] => /opt/lampp/temp/php0yPZap
)

[error] => 数组
(
[avatar] => 0
[attachment] => 0
)

[size] => 数组
(
[avatar] => 1960
[attachment] => 8661
)

)

[upload2] => Array
(
[name] => 数组
(
[avatar] => jefrey.html
[attachment] => notas.txt
)

[type] => 数组
(
[avatar] => text/html
[attachment] => text/plain
)

[tmp_name] => 数组
(
[avatar] => /opt/lampp/temp/php87nfyu
[attachment] => /opt/lampp/temp/phpUBlvVz
)

[error] => 数组
(
[avatar] => 0
[attachment] => 0
)

[size] => 数组
(
[avatar] => 583
[attachment] => 191
)

)

)

我成功地将这个数组重新排列成了这样

数组
(
[upload] => Array
(
[avatar] => Array
(
[name] => teste.c
[type] => text/x-csrc
[tmp_name] => /opt/lampp/temp/phpuf3KNj
[error] => 0
[size] => 1960
)

[attachment] => Array
(
[name] => teste
[type] => application/octet-stream
[tmp_name] => /opt/lampp/temp/php0yPZap
[error] => 0
[size] => 8661
)

)

[upload2] => Array
(
[avatar] => Array
(
[name] => jefrey.html
[type] => text/html
[tmp_name] => /opt/lampp/temp/php87nfyu
[error] => 0
[size] => 583
)

[attachment] => Array
(
[name] => notas.txt
[type] => text/plain
[tmp_name] => /opt/lampp/temp/phpUBlvVz
[error] => 0
[size] => 191
)

)

)

这是我的代码片段
<?php
function reArrayFilesMultiple(&$files) {
$uploads = array();
foreach(
$_FILES as $key0=>$FILES) {
foreach(
$FILES as $key=>$value) {
foreach(
$value as $key2=>$value2) {
$uploads[$key0][$key2][$key] = $value2;
}
}
}
$files = $uploads;
return
$uploads; // 防止误用问题
}
?>
-32
javad dot geek at gmail dot com
10 年前
$countarray = count($_FILES['uploadfile']['name']);
$newarray = array();
for($i=0;$i<$countarray;$i++){
$newarray[$i]['name']=$_FILES['uploadfile']['name'][$i];
$newarray[$i]['type']=$_FILES['uploadfile']['type'][$i];
$newarray[$i]['tmp_name']=$_FILES['uploadfile']['tmp_name'][$i];
$newarray[$i]['error']=$_FILES['uploadfile']['error'][$i];
$newarray[$i]['size']=$_FILES['uploadfile']['size'][$i];
}
-4
simbiat at outlook dot com
3 年前
虽然 phpuser.at.gmail.dot.com 的代码很好,而且 i.g.e.o@ya.(dot).ru 的代码更好,但完美永远没有尽头。我们可以不用临时变量
<?php
foreach ($_FILES as $field=>$files) {
# 检查是否有多个文件上传到一个字段,并相应处理值
if (is_array($files['name'])) {
foreach (
$files['name'] as $key=>$file) {
$_FILES[$field][$key]['name'] = $file;
$_FILES[$field][$key]['type'] = $files['type'][$key];
$_FILES[$field][$key]['size'] = $files['size'][$key];
$_FILES[$field][$key]['tmp_name'] = $files['tmp_name'][$key];
$_FILES[$field][$key]['error'] = $files['error'][$key];
}
} else {
$_FILES[$field][0]['name'] = $files['name'];
$_FILES[$field][0]['type'] = $files['type'];
$_FILES[$field][0]['size'] = $files['size'];
$_FILES[$field][0]['tmp_name'] = $files['tmp_name'];
$_FILES[$field][0]['error'] = $files['error'];
}
unset(
$_FILES[$field]['name'], $_FILES[$field]['type'], $_FILES[$field]['size'], $_FILES[$field]['tmp_name'], $_FILES[$field]['error']);
}
?>
-36
ohcnim at hotmail dot com
10 年前
只需为每个文件输入命名不同,你就可以轻松地从 $_FILES 获取可访问的数组,形式为 $_FILES['input_name']['file_attribute']。例如

$_FILES['input_name1']['name']...['input_name1']['size']
$_FILES['input_name2']['name']...['input_name2']['size']
$_FILES['input_nameX']['name']...['input_nameX']['size']
-34
Pako
8 年前
如果你想一次上传多个文件,请记住 “multiple” 属性

<input type="file" multiple="multiple" name="file[]" enctype="multipart/form-data"/>
-31
Roman
8 年前
function reorganize($files) {
foreach ($files as $var => $params) {
foreach ($params as $name => $i) {
foreach ($i as $num => $val) {
$images[$var][$name] = $val;
$arr[$num] = $images;
}
}
}
return $arr;
}

Array (
[0] => Array (
[image] => Array (
[name] => white-rabbit-med-crop.jpg
[type] => image/jpeg
[tmp_name] => E:\xampp\tmp\phpC008.tmp
[error] => 0
[size] => 343326 )
)
[1] => Array (
[image] => Array (
[name] => white-rabbit-med-crop.jpg
[type] => image/jpeg
[tmp_name] => E:\xampp\tmp\phpC008.tmp
[error] => 0
[size] => 1429802 )
)
)
To Top