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

PHP 文件上傳存入資料庫完整實現(含舊版 mysql_* 代碼現代化遷移指南)

     編輯:PHP 相關知識

PHP 文件上傳存入資料庫完整實現

本文示範將上傳文件二進位內容直接寫入 MySQL `BLOB` 欄位的完整流程。**注意:原文使用已棄用移除的 `mysql_*` 函數,下方代碼已升級為 PDO 預處理語句,防止 SQL 注入並相容 PHP 7/8。**

資料表結構

CREATE TABLE `receive` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `file_name` VARCHAR(255) NOT NULL,
  `file_type` VARCHAR(100) NOT NULL,
  `file_size` INT UNSIGNED NOT NULL,
  `file_data` LONGBLOB NOT NULL,
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心流程四檔案

1. `upload.php` — 上傳表單

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>文件上傳</title></head><body>
<form action="submit.php" method="post" enctype="multipart/form-data">
  <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
  <p>選擇檔案:<input type="file" name="myfile"></p>
  <p><input type="submit" name="submit" value="上傳"></p>
</form>
</body></html>

2. `submit.php` — 處理上傳、寫入資料庫

<?php
require_once 'db.php';

if (!isset($_FILES['myfile']) || $_FILES['myfile']['error'] !== UPLOAD_ERR_OK) {
    die('未收到有效上傳檔案或上傳出錯:' . ($_FILES['myfile']['error'] ?? '未知'));
}

$file = $_FILES['myfile'];
$tmp  = $file['tmp_name'];

// 讀取二進位內容
$data = file_get_contents($tmp);
if ($data === false) die('讀取暫存檔失敗');

// 刪除暫存檔 (PHP 會在腳本結束自動清理,顯式調用更保險)
@unlink($tmp);

// 準備元資料
$name = $file['name'];
$type = $file['type'] ?: 'application/octet-stream';
$size = $file['size'];

// 寫入資料庫 (PDO 預處理,防注入)
try {
    $pdo = getPDO(); // 見 db.php
    $stmt = $pdo->prepare(
        'INSERT INTO `receive` (file_name, file_type, file_size, file_data) VALUES (?, ?, ?, ?)'
    );
    $stmt->bindParam(1, $name, PDO::PARAM_STR);
    $stmt->bindParam(2, $type, PDO::PARAM_STR);
    $stmt->bindParam(3, $size, PDO::PARAM_INT);
    $stmt->bindParam(4, $data, PDO::PARAM_LOB); // 關鍵:LOB 參數綁定
    $stmt->execute();

    $id = $pdo->lastInsertId();
    echo "上傳成功!<a href='show_info.php?id=$id'>查看檔案資訊</a>";
} catch (PDOException $e) {
    error_log('Upload DB Error: ' . $e->getMessage());
    die('資料庫寫入失敗,請稍後重試');
}

3. `show_info.php` — 顯示檔案元資訊

<?php
require_once 'db.php';
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$id) die('缺少 ID');

$pdo = getPDO();
$stmt = $pdo->prepare('SELECT file_name, file_size FROM receive WHERE id = ?');
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$row) die('記錄不存在');

echo "<hr>上傳檔案資訊:<br>";
echo "檔案名:{$row['file_name']}<br>";
echo "大小:{$row['file_size']} bytes<br>";
echo "<a href='show_file.php?id=$id'>下載檔案</a>";

4. `show_file.php` — 輸出檔案供下載

<?php
require_once 'db.php';
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (!$id) die('缺少 ID');

$pdo = getPDO();
$stmt = $pdo->prepare('SELECT file_data, file_type, file_name FROM receive WHERE id = ?');
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$row) die('記錄不存在');

// 輸出檔案頭
header('Content-Type: ' . $row['file_type']);
header('Content-Disposition: attachment; filename="' . rawurlencode($row['file_name']) . '"');
header('Content-Length: ' . strlen($row['file_data']));
echo $row['file_data'];

5. `db.php` — PDO 連線單例

<?php
function getPDO()
{
    static $pdo = null;
    if ($pdo === null) {
        $dsn = 'mysql:host=127.0.0.1;dbname=test;charset=utf8mb4';
        $pdo = new PDO($dsn, 'username', 'password', [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES   => false, // 使用真實預處理
        ]);
    }
    return $pdo;
}

關鍵最佳實踐總結

  1. PDO + 預處理 + PARAM_LOB:唯一正確處理 BLOB 寫入的方式,自動處理轉義、大物件流式傳輸。
  2. 檔案大小限制:`MAX_FILE_SIZE` 表單隱藏欄位僅供瀏覽器參考,**伺服器端必須驗證** `$_FILES['size']` 並配置 `upload_max_filesize`、`post_max_size`、`memory_limit`。
  3. MIME 類型不可信:`$_FILES['type']` 來自瀏覽器,易偽造。生產環境請用 `finfo_file()` 或 `mime_content_type()` 二次檢測。
  4. 大檔案考量:超過數十 MB 建議改存檔案系統/對象儲存 (S3/OSS),資料庫僅存路徑,避免記憶體暴漲、備份緩慢、複制延遲。
  5. 安全下載:`show_file.php` 應加入權限檢查(登入狀態、擁有者驗證),防止枚舉 ID 遍歷下載。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved