©
This document uses PHP Chinese website manual Release
可以对 input 域使用不同的 name 来上传多个文件。
PHP 支持同时上传多个文件并将它们的信息自动以数组的形式组织。要完成这项功能,需要在 HTML 表单中对文件上传域使用和多选框与复选框相同的数组式提交语法。
Note:
对多文件上传的支持是在 PHP 3.0.10 版本添加的。
Example #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'] 将被初始化(在 PHP 4.1.0 以前版本是 $HTTP_POST_FILES )。如果 register_globals 的设置为 on,则和文件上传相关的全局变量也将被初始化。所有这些提交的信息都将被储存到以数字为索引的数组中。
例如,假设名为 /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] 。
[#1] Eric [2015-11-28 11:17:06]
This is just a modification of the code which is the top note by "phpuser" here. His/her version requires that the $file_post array passed in to the function was created by a form submitted with the multiple attribute set. With multiple set in the html input tag, $_FILES["fileInputName"]["name"] is an array no matter if only one file is sent or multiple. But when <input type="file"> is used without the multiple attribute then $_FILES["fileInputName"]["name"] is not an array, it contains the the string with the filename. To use this neat function with or without multiple set and to get back an array which you can "foreach" over in either case, use this modification:
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;
}
[#2] Roman [2015-10-29 12:56:32]
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 )
)
)
[#3] swayalex at gmail dot com [2015-10-21 14:20:34]
Recursive solution for complex situations (supports any nested arrays including indexed arrays)
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) {
// init for array_merge
if (!isset($files[$name])) {
$files[$name] = array();
}
if (!is_array($values['error'])) {
// normal syntax
$files[$name] = $values;
} else {
// html array feature
foreach ($values as $fileInfoKey => $subArray) {
$files[$name] = array_replace_recursive($files[$name], $walker($subArray, $fileInfoKey, $walker));
}
}
}
return $files;
}
[#4] Pako [2015-08-25 13:30:09]
If you want to upload multiple file at once, remember "multiple" attribute:
<input type="file" multiple="multiple" name="file[]" enctype="multipart/form-data"/>
[#5] javad dot geek at gmail dot com [2014-02-07 14:14:42]
$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];
}
[#6] wizzard351 at yahoo dot com [2014-01-27 18:12:08]
This is also needed for <input type=file multiple> elements.
So, if you have an input element like this:
<input type="file" multiple="multiple" name="foobar" />
This should be written as
<input type="file" multiple="multiple" name="foobar[]" />
else you'll only be able to get one of the files.
[#7] ohcnim at hotmail dot com [2013-08-16 23:18:24]
by simply naming differently each file input you'll get easily accesible arrays from $_FILES, in the form $_FILES['input_name']['file_attribute']. For example:
$_FILES['input_name1']['name']...['input_name1']['size']
$_FILES['input_name2']['name']...['input_name2']['size']
$_FILES['input_nameX']['name']...['input_nameX']['size']
[#8] timspeelman at live dot nl [2011-11-18 15:48:16]
The cleanest way to rearrange the $_FILES
<?php
function rearrange( $arr ){
foreach( $arr as $key => $all ){
foreach( $all as $i => $val ){
$new[$i][$key] = $val;
}
}
return $new;
}
?>
[#9] contato at dgmike dot com dot br [2011-07-19 11:33:03]
I prefer something like this!
<?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] Corey Ballou [2010-03-25 13:10:39]
Here is a function to fix the indices of a multi-dimensional for easier parsing when dealing with file uploads. It takes a single $_FILES field array as a parameter and separates each individual uploaded file by numeric key. This allows for iterating like:
<?php
fixFilesArray($_FILES['array_of_files']);
foreach ($_FILES['array_of_files'] as $position => $file) {
// should output array with indices name, type, tmp_name, error, size
var_dump($file);
}
?>
Here's the code:
<?php
function fixFilesArray(&$files)
{
$names = array( 'name' => 1, 'type' => 1, 'tmp_name' => 1, 'error' => 1, 'size' => 1);
foreach ($files as $key => $part) {
// only deal with valid keys and multiple files
$key = (string) $key;
if (isset($names[$key]) && is_array($part)) {
foreach ($part as $position => $value) {
$files[$position][$key] = $value;
}
// remove old key reference
unset($files[$key]);
}
}
}
?>
[#11] jess at semlabs dot co dot uk [2009-03-03 12:32:27]
If you try and upload files with multi-dimensional names like this:
<input type="file" name="submission[screenshot]" />
<input type="file" name="other[dem][][img][]" />
You will get an unexpected format like this:
<?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 ),
),
....
?>
You can use the following function to re-format the array recursively in the usual format:
<?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;
}
?>
[#12] hotmail.com[at]notdefix [2007-09-27 07:47:33]
With multiple file uploads
post_max_size: the total amount of data posted by the client (all files, and all other form field)
upload_max_filesize: the maximum size of 1 single file. (just like <input type="hidden" name="MAX_FILE_SIZE" value="..."/>)
so, with the directives:
post_max_size 25M
upload_max_filesize 2M
you can send 12 files of up to 2 MB and use up to 1 MB for your additional form-values.
As long as you read only a single copy of 1 file into memory, the memory_limit directive can be held reasonable small as well.
[#13] phpuser at gmail dot com [2005-05-26 08:09:40]
When uploading multiple files, the $_FILES variable is created in the form:
Array
(
[name] => Array
(
[0] => foo.txt
[1] => bar.txt
)
[type] => Array
(
[0] => text/plain
[1] => text/plain
)
[tmp_name] => Array
(
[0] => /tmp/phpYzdqkD
[1] => /tmp/phpeEwEWG
)
[error] => Array
(
[0] => 0
[1] => 0
)
[size] => Array
(
[0] => 123
[1] => 456
)
)
I found it made for a little cleaner code if I had the uploaded files array in the form
Array
(
[0] => Array
(
[name] => foo.txt
[type] => text/plain
[tmp_name] => /tmp/phpYzdqkD
[error] => 0
[size] => 123
)
[1] => Array
(
[name] => bar.txt
[type] => text/plain
[tmp_name] => /tmp/phpeEwEWG
[error] => 0
[size] => 456
)
)
I wrote a quick function that would convert the $_FILES array to the cleaner (IMHO) array.
<?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;
}
?>
Now I can do the following:
<?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'];
}
}
?>