:::
4-4 檔案上傳與接收
一、單一個檔案的上傳基本概念
- 若表單中有
file元件,其表單一定要加上enctype="multipart/form-data" - 假設
file欄位名稱為media(先將[]及multiple拿掉,也就是只上傳一個檔),如此送出後會產生一組$_FILES超級全域變數(二維陣列):$_FILES['media']['name']:上傳檔案原始名稱。$_FILES['media']['type']:檔案的 MIME 類型,例如“image/gif”。$_FILES['media']['size']:已上傳檔案的大小,單位為bytes。$_FILES['media']['tmp_name']:檔案被上傳後的臨時檔案名。$_FILES['media']['error']:和該檔案上傳相關的錯誤代碼。
- 上傳的步驟:送出上傳 → 檔案會暫時放到主機的暫存目錄(如:tmp中) → 程式要搬移該暫存檔
$_FILES['media']['tmp_name']到指定的位置。 - 搬移上傳檔方法:
move_uploaded_file($_FILES['media']['tmp_name'], 新路徑檔名);
二、多個檔案的上傳基本概念:
- 假設 file 欄位名稱為
media,多檔上傳的name屬性必須加上[]及multiple屬性,如:<input type="file" name="media[]" id="files" class="form-control" placeholder="請上傳相片或影片" accept=".jpg,.jpeg,.png,.gif,.mp4" multiple /> - 假設選了兩個檔送出後
$_FILES超級全域變數會變成像這樣(三維陣列):- 第一個檔案
$_FILES['media']['name'][0]:第一個檔案原始名稱。$_FILES['media']['type'][0]:第一個檔案的 MIME 類型,例如“image/gif”。$_FILES['media']['size'][0]:第一個檔案的大小,單位為bytes。$_FILES['media']['tmp_name'][0]:第一個檔案被上傳後的臨時檔案名。$_FILES['media']['error'][0]:第一個檔案上傳相關的錯誤代碼。
- 第二個檔案
$_FILES['media']['name'][1]:第二個檔案原始名稱。$_FILES['media']['type'][1]:第二個檔案的 MIME 類型,例如“image/gif”。$_FILES['media']['size'][1]:第二個檔案的大小,單位為bytes。$_FILES['media']['tmp_name'][1]:第二個檔案被上傳後的臨時檔案名。$_FILES['media']['error'][1]:第二個檔案上傳相關的錯誤代碼。
- 第一個檔案
三、調整我們的上傳語法:
- 先用 file_exists() 檢查目錄是否存在,若不存在就建立上傳目錄。而目錄會根據文章
id編號來建立子目錄,例如id=12的文章,其目錄路徑就是/uploads/12/,這樣可以避免圖檔互相覆蓋,避免誤刪或者未來要刪除文章時也比較容易刪掉附檔。// 取得插入的 id 值 $lastInsertId = $pdo->lastInsertId(); // 建立存放圖檔的目錄 $articleDir = $uploadDir . $lastInsertId . '/'; if (!file_exists($articleDir)) { mkdir($articleDir, 0777, true); }其中
0777是指任何人都可以寫入,而最後的true則是連同父目錄都一併建立 -
我們的上傳欄位為:
<input type="file" class="form-control" id="media" name="media[]" multiple accept=".png, .jpg, .gif, .mp4">所以需要用
foreach()迴圈來讀取$_FILES['media'],以便一個檔一個檔抽出來,用 move_uploaded_file() 完成上傳動作。上傳檔案的語法:// 處理多檔案上傳 if (!empty($_FILES['media'])) { $fileData = array(); foreach ($_FILES['media']['name'] as $index => $fileName) { $fileTmpName = $_FILES['media']['tmp_name'][$index]; $fileDestination = $articleDir . $fileName; // 將檔案移動到文章檔案目錄 move_uploaded_file($fileTmpName, $fileDestination); // 將檔案路徑存入陣列 $fileData[$fileName] = $fileDestination; } // 將檔案相關資訊轉換為JSON格式 $media = json_encode($fileData, 256); // 更新該文章的 media 欄位值 } - 檔案上傳後,我們必須把所有檔案資訊記錄下來,這樣日後讀出時,才能知道此文章有把些檔案。其中
$fileData就是用來儲存所有上傳的檔案陣列,$fileName是檔名,用來作為$fileData的陣列索引;$fileDestination則是檔案路徑,為陣列值。 - 最後,只要將
$fileData資料用 json_encode() 編成JSON格式(加上JSON_UNESCAPED_UNICODE參數可以讓中文正確呈現,否則會用Unicode編碼,不過JSON_UNESCAPED_UNICODE太難記,所以可以直接輸入其對應值256就好),再寫進資料庫就OK囉!// 將檔案相關資訊轉換為JSON格式 $media = json_encode($fileData, 256);
4-3 用PDO寫入資料庫