File Upload

上傳檔案

2019/11/16 (更新內容)

基本概念

php.ini (先確認一下是否將file_uploads設為On)

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Whether to allow HTTP file uploads.
; http://php.net/file-uploads
file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
; http://php.net/upload-tmp-dir
;upload_tmp_dir =

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 2M

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

首先,先新增一個form,因為要上傳檔案,enctype要設定為multipart/form-data,另外,利用file元件讓使用者選擇檔案。

fileupload.php

<!DOCTYPE html>
<html>
<body>

<form action="fileupload_process.php" method="post" enctype="multipart/form-data">
    選擇圖片:
    <input type="file" name="fileToUpload" id="fileToUpload"><br>
    <input type="submit" value="上傳圖片" name="submit">
</form>

</body>
</html>

php會把上傳的檔案及相關資料放到$_FILES

fileupload_process.php:

<?php
var_dump($_FILES);
?>

我們會看到類似這樣的內容:

array(1) { ["fileToUpload"]=> array(5) { ["name"]=> string(6) "19.jpg" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(26) "C:\Windows\Temp\php75D.tmp" ["error"]=> int(0) ["size"]=> int(45262) } }

基本上,$_FILES裡包含一個陣列,陣列的名稱是我們給file元件的名稱(fileToUpload),陣列內容包括檔案的名稱、資料型態、暫存檔的名稱、錯誤代碼、檔案大小。

基本上檔案已經上傳成功了,只是,目前是暫存在暫存目錄中,所以我們要把檔案移到apache伺服器下的目錄,PHP提供了一個指令move_uploaded_file來進行這個動作 (詳參: move_uploaded_file() Function)。

fileupload_process.php的內容改成:

<?php
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $_FILES["fileToUpload"]["name"]);
header('location:fileupload.php');
?>

基本上就可以從檔案管理員裡看到檔案了。

接下來,我們來修改一下fileupload_process.php,把檔案名稱傳到fileupload.php

<?php
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $_FILES["fileToUpload"]["name"]);
header('location:fileupload.php?name='.$_FILES["fileToUpload"]["name"]);
?>

接下來,我們來修改一下fileupload.php

<?php
$filename=$_GET["name"]??"";
?>
<!DOCTYPE html>
<html>

<body>

  <form action="fileupload_process.php" method="post" enctype="multipart/form-data">
  選擇圖片:
  <input type="file" name="fileToUpload" id="fileToUpload"><br>
  <input type="submit" value="上傳圖片" name="submit">
 </form>
 <img src="<?=$filename?>" alt="<?=$filename?>" width="30%">

</body>
</html>

看到圖片了!

顯示資料夾內所有檔案

//reference: http://blog.yam.com/clayclay76/article/52362255
function list_all_file_as_image($dir_path)
{
    if(is_dir($dir_path))
    {
        foreach(scandir($dir_path) as $file)
        {
            if($file != '.' && $file != '..')
            {
                list_all_file_as_image($dir_path . '/' . $file);
            }
        }
    }
    
    if(is_file($dir_path))
    {
        echo "<img src='$dir_path'>"."\n";
    }
}

錯誤處理

一般而言,都會在php.ini中設定了檔案大小的上限,所以,當我們傳了一個超過2MB的檔案,會看不到內容。

怎麼知道有錯誤發生呢? 可以檢查$_FILES["fileToUpload"]["error"],當內容是0的時候,就是沒有錯誤,當內容是1的時候,就是檔案超過2MB (詳參: Error Messages Explained & POST method uploads)。

fileupload_process.php

<?php
$error = $_FILES["fileToUpload"]["error"];
$filename = $_FILES["fileToUpload"]["name"];
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $filename);
header('location:fileupload.php?error='.$error.'&name='.$filename);

?>

修改fileupload.php,處理錯誤訊息。

<?php
$filename = $_GET["name"]??"";
$error = $_GET["error"]??"";
$phpFileUploadErrors = [
 0 => '上傳成功',
 1 => '檔案大小超過伺服器設定(2MB)!',
 2 => '檔案大小超過瀏覽器設定!',
 3 => '上傳檔案不完整',
 4 => '未上傳檔案',
 6 => '暫存資料夾不存在',
 7 => '無法寫入檔案',
 8 => 'PHP擴充導致檔案無法上傳',
];

$msg = $phpFileUploadErrors[$error]??"";

?>
<!DOCTYPE html>
<html>

<body>

 <form action="fileupload_process.php" method="post" enctype="multipart/form-data">
  選擇圖片:
  <input type="file" name="fileToUpload" id="fileToUpload"><br>
  <input type="submit" value="上傳圖片" name="submit">
 </form>
 <?=$msg?><br>
 <img src="<?=$filename?>" alt="<?=$filename?>" width="30%">
</body>

</html>

例外處理

檔案類型

檢查檔案類型很重要,我們不希望收到一個無法顯示的圖檔,甚至是個會把檔案都刪掉的執行檔(被植入木馬)

檔案是否已存在

參考資料