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

PHP 圖片上傳並等比壓縮縮略圖(GD 實現)

     編輯:PHP 綜合知識

核心需求

  • 上傳圖片 → 驗證類型/大小 → 儲存原圖
  • 生成縮略圖:等比縮放、限制最大寬高、不足處填充白邊(或直接裁切)

完整實現類

class ImageUploader {
    private $maxWidth = 800;
    private $maxHeight = 600;
    private $thumbWidth = 200;
    private $thumbHeight = 200;
    private $saveDir = 'uploads/';
    private $allowedTypes = ['image/jpeg','image/png','image/gif','image/webp'];
    private $allowedExt = ['jpg','jpeg','png','gif','webp'];

    public function upload($fileInputName = 'file') {
        if (!isset($_FILES[$fileInputName]) || $_FILES[$fileInputName]['error'] !== UPLOAD_ERR_OK) {
            throw new Exception('上傳失敗或無文件');
        }
        $file = $_FILES[$fileInputName];
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($ext, $this->allowedExt) || !in_array($file['type'], $this->allowedTypes)) {
            throw new Exception('不支援的文件類型');
        }
        if (!is_dir($this->saveDir)) mkdir($this->saveDir, 0755, true);
        $filename = uniqid('img_', true).'.'.$ext;
        $dest = $this->saveDir.$filename;
        if (!move_uploaded_file($file['tmp_name'], $dest)) {
            throw new Exception('移動文件失敗');
        }
        // 原圖若超過限制,先壓縮
        $this->resizeIfNeeded($dest, $this->maxWidth, $this->maxHeight);
        // 生成縮略圖
        $thumbName = 'thumb_'.$filename;
        $thumbPath = $this->saveDir.$thumbName;
        $this->createThumbnail($dest, $thumbPath, $this->thumbWidth, $this->thumbHeight);
        return ['original'=>$dest, 'thumbnail'=>$thumbPath];
    }

    private function resizeIfNeeded($path, $maxW, $maxH) {
        list($w, $h, $type) = getimagesize($path);
        if ($w <= $maxW && $h <= $maxH) return;
        $ratio = min($maxW/$w, $maxH/$h);
        $newW = (int)($w*$ratio); $newH = (int)($h*$ratio);
        $this->resample($path, $path, $newW, $newH, $type);
    }

    private function createThumbnail($src, $dst, $maxW, $maxH, $bgColor = [255,255,255]) {
        list($w, $h, $type) = getimagesize($src);
        $ratio = min($maxW/$w, $maxH/$h);
        $newW = (int)($w*$ratio); $newH = (int)($h*$ratio);
        $canvas = imagecreatetruecolor($maxW, $maxH);
        $bg = imagecolorallocate($canvas, $bgColor[0], $bgColor[1], $bgColor[2]);
        imagefill($canvas, 0, 0, $bg);
        $x = ($maxW - $newW) / 2; $y = ($maxH - $newH) / 2;
        $srcIm = $this->createFromType($src, $type);
        imagecopyresampled($canvas, $srcIm, $x, $y, 0, 0, $newW, $newH, $w, $h);
        $this->saveByType($canvas, $dst, $type);
        imagedestroy($srcIm); imagedestroy($canvas);
    }

    private function resample($src, $dst, $newW, $newH, $type) {
        $srcIm = $this->createFromType($src, $type);
        $dstIm = imagecreatetruecolor($newW, $newH);
        imagecopyresampled($dstIm, $srcIm, 0, 0, 0, 0, $newW, $newH, imagesx($srcIm), imagesy($srcIm));
        $this->saveByType($dstIm, $dst, $type);
        imagedestroy($srcIm); imagedestroy($dstIm);
    }

    private function createFromType($path, $type) {
        switch ($type) {
            case IMAGETYPE_JPEG: return imagecreatefromjpeg($path);
            case IMAGETYPE_PNG:  return imagecreatefrompng($path);
            case IMAGETYPE_GIF:  return imagecreatefromgif($path);
            case IMAGETYPE_WEBP: return imagecreatefromwebp($path);
            default: throw new Exception('Unsupported type');
        }
    }
    private function saveByType($im, $path, $type) {
        switch ($type) {
            case IMAGETYPE_JPEG: imagejpeg($im, $path, 90); break;
            case IMAGETYPE_PNG:  imagepng($im, $path, 8); break;
            case IMAGETYPE_GIF:  imagegif($im, $path); break;
            case IMAGETYPE_WEBP: imagewebp($im, $path, 90); break;
        }
    }
}

// 使用
$uploader = new ImageUploader();
try {
    $result = $uploader->upload('avatar');
    echo json_encode(['code'=>0,'data'=>$result]);
} catch (Exception $e) {
    echo json_encode(['code'=>1,'msg'=>$e->getMessage()]);
}

關鍵點解析

步驟函數說明
讀取圖片imagecreatefromjpeg/png/gif/webp根據 getimagesize() 返回的類型常量選擇
建立畫布imagecreatetruecolor()真彩色畫布,支援透明度(PNG/GIF 需額外處理)
等比縮放imagecopyresampled()雙線性插值,品質優於 imagecopyresized()
填充背景imagefill()縮略圖畫布預填白色,居中貼圖
輸出imagejpeg/png/gif/webp()JPEG 品質 90,PNG 壓縮 8

透明度保留(PNG/GIF)

// 在 createThumbnail 中,若原圖有透明通道
if ($type === IMAGETYPE_PNG || $type === IMAGETYPE_GIF) {
    imagealphablending($canvas, false);
    imagesavealpha($canvas, true);
    $transparent = imagecolorallocatealpha($canvas, 0,0,0,127);
    imagefill($canvas,0,0,$transparent);
    // ... 複製貼圖
}

總結

封裝 ImageUploader 類,統一處理「驗證 → 原圖壓縮 → 縮略圖生成」。核心 API:getimagesize() 獲取屬性 → imagecreatetruecolor() 建畫布 → imagecopyresampled() 高質量縮放 → imagefill() 背景填充 → 對應輸出函數落盤。可直接投入生產或擴展為 Laravel/ThinkPHP 服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved