PHP Conference Japan 2024

上傳多個檔案

可以使用不同的 inputname 屬性來上傳多個檔案。

也可以同時上傳多個檔案,並將資訊自動整理成陣列。要這樣做,您需要在 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 屬性並非標準屬性,且不在標準化軌道上。請勿在面向網路的正式網站上使用它:它並不會適用於所有使用者。不同實作之間可能也存在很大的不相容性,而且其行為在未來可能會改變。

PHP 只會解析瀏覽器/使用者代理程式提交的相對路徑資訊,並將該資訊傳遞給 $_FILES 陣列。無法保證 full_path 陣列中的值包含真實的目錄結構,PHP 應用程式不應信任此資訊。

新增註解

使用者貢獻的註解 8 則註解

353
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'];
print
'檔案類型:' . $file['type'];
print
'檔案大小:' . $file['size'];
}
}

?>
18
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;
}
?>
50
wizzard351 at yahoo dot com
10 年前
這也適用於 <input type=file multiple> 元素。

因此,如果您有像這樣的輸入元素
<input type="file" multiple="multiple" name="foobar" />
應該寫成這樣
<input type="file" multiple="multiple" name="foobar[]" />
否則您只能取得其中一個檔案。
1
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) {
// 將檔案儲存到本地
}
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
13 年前
重新排列 $_FILES 最簡潔的方法

<?php
function rearrange( $arr ){
foreach(
$arr as $key => $all ){
foreach(
$all as $i => $val ){
$new[$i][$key] = $val;
}
}
return
$new;
}
?>
6
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" 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
4 年前
函式 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