首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 文件上傳入門教程:從表單到 move_uploaded_file 核心流程詳解

     編輯:PHP 相關知識

完整上傳流程圖解

用戶選擇檔案 → 表單提交 (multipart/form-data)
                    ↓
PHP 接收 → $_FILES 陣列暫存資訊
                    ↓
驗證 (類型、大小、錯誤碼)
                    ↓
move_uploaded_file(tmp_name, 目標路徑)
                    ↓
成功/失敗回應

HTML 表單(必要屬性)

<form action="upload_file.php" method="post" enctype="multipart/form-data">
  <label for="file">選擇檔案:</label>
  <input type="file" name="file" id="file" />
  <br>
  <input type="submit" name="submit" value="上傳" />
</form>

三大關鍵:

  1. method="post":GET 無法傳檔案
  2. enctype="multipart/form-data":編碼類型,必須
  3. type="file":瀏覽器顯示「選擇檔案」按鈕

PHP 處理腳本 (upload_file.php)

<?php
// 簡單版:核心只有這兩行
$targetDir = 'uploads/';
$targetFile = $targetDir . basename($_FILES['file']['name']);

if (move_uploaded_file($_FILES['file']['tmp_name'], $targetFile)) {
  echo "上傳成功!檔案儲存於:$targetFile";
} else {
  echo "上傳失敗。";
}

生產環境安全版(必看)

<?php
function uploadFile(array $file, string $targetDir = 'uploads/'): array {
  // 1. 檢查錯誤碼
  if ($file['error'] !== UPLOAD_ERR_OK) {
    return ['success' => false, 'error' => '上傳錯誤代碼: ' . $file['error']];
  }

  // 2. 檢查檔案大小 (2MB)
  if ($file['size'] > 2 * 1024 * 1024) {
    return ['success' => false, 'error' => '檔案超過 2MB 限制'];
  }

  // 3. 驗證 MIME 類型 (用 finfo,不可信 $_FILES['type'])
  $finfo = new finfo(FILEINFO_MIME_TYPE);
  $mime = $finfo->file($file['tmp_name']);
  $allowed = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];
  if (!in_array($mime, $allowed)) {
    return ['success' => false, 'error' => "不支援的檔案類型: $mime"];
  }

  // 4. 驗證副檔名
  $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
  $allowedExt = ['jpg','jpeg','png','gif','pdf'];
  if (!in_array($ext, $allowedExt)) {
    return ['success' => false, 'error' => "不允許的副檔名: $ext"];
  }

  // 5. 確保目錄存在且可寫
  if (!is_dir($targetDir)) {
    mkdir($targetDir, 0755, true);
  }

  // 6. 生成唯一檔名 (防覆蓋、防猜測、防中文亂碼)
  $newName = bin2hex(random_bytes(16)) . '.' . $ext;
  $targetPath = $targetDir . $newName;

  // 7. 移動檔案
  if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
    return ['success' => false, 'error' => '檔案移動失敗,請檢查目錄權限'];
  }

  // 8. 設定權限
  chmod($targetPath, 0644);

  return [
    'success' => true,
    'filename' => $newName,
    'path' => $targetPath,
    'size' => $file['size'],
    'mime' => $mime
  ];
}

// 使用
$result = uploadFile($_FILES['file']);
if ($result['success']) {
  echo "上傳成功:" . $result['path'];
} else {
  echo "失敗:" . $result['error'];
}

$_FILES 陣列完整結構

鍵名說明範例
name客戶端原始檔名photo.jpg
type瀏覽器報告 MIME (不可信)image/jpeg
tmp_name伺服器暫存路徑/tmp/phpA1B2C3
size檔案大小 (bytes)102400
error錯誤代碼 (0=成功)0

常見錯誤代碼對照

常數值原因解決
UPLOAD_ERR_OK0成功—
UPLOAD_ERR_INI_SIZE1超過 php.ini upload_max_filesize調大 php.ini 或 .user.ini
UPLOAD_ERR_FORM_SIZE2超過表單 MAX_FILE_SIZE移除隱藏欄位或調大
UPLOAD_ERR_PARTIAL3僅部分上傳 (網路中斷)重試、檢查網路
UPLOAD_ERR_NO_FILE4未選擇檔案前端驗證必填
UPLOAD_ERR_NO_TMP_DIR6缺少暫存目錄php.ini 設定 upload_tmp_dir
UPLOAD_ERR_CANT_WRITE7寫入磁碟失敗檢查磁碟空間/權限
UPLOAD_ERR_EXTENSION8PHP 擴展阻止檢查 suhosin 等擴展

php.ini 關鍵設定

file_uploads = On
upload_max_filesize = 10M
post_max_size = 12M          ; 必須 > upload_max_filesize
max_file_uploads = 20        ; 單次最多檔案數
upload_tmp_dir = /tmp/php_uploads  ; 需存在且可寫
max_execution_time = 60
memory_limit = 128M

多檔案上傳

<!-- HTML: name 結尾加 [] -->
<input type="file" name="files[]" multiple />

<?php
// PHP: 遍歷陣列
foreach ($_FILES['files']['tmp_name'] as $index => $tmpName) {
  $file = [
    'name'     => $_FILES['files']['name'][$index],
    'type'     => $_FILES['files']['type'][$index],
    'tmp_name' => $tmpName,
    'size'     => $_FILES['files']['size'][$index],
    'error'    => $_FILES['files']['error'][$index],
  ];
  $result = uploadFile($file);
  // 處理結果...
}

進階主題導引

  • 大檔案分片上傳:前端切片 (Blob.slice),後端合併,支援斷點續傳
  • 雲端直傳:後端簽名 Policy,前端直傳 OSS/S3,減輕伺服器
  • 圖片處理管線:上傳後自動壓縮、生成縮圖、水印、WebP 轉換
  • 病毒掃描:整合 ClamAV 掃描暫存檔
  • 進度條:Session 上傳進度 (session.upload_progress) 或 XMLHttpRequest upload 事件
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved