You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现图片/PDF存储前压缩至1MB以内的需求及代码咨询

解决PHP中存储前压缩图片/PDF至1MB以内的方案

Hey there! 针对你现在直接将图片/PDF内容存入数据库、需要在存储前把文件大小控制在1MB以内的需求,我分两种场景整理了可直接整合的实现方案,兼顾压缩效果和文件完整性:

一、核心思路

先判断文件类型:

  • 图片文件:优先通过调整压缩质量+缩放尺寸来降低大小
  • PDF文件:借助Ghostscript进行优化压缩(需要服务器支持)
  • 最后统一检查处理后的文件大小,确保不超过1MB

二、完整代码实现

$maxFileSize = 1 * 1024 * 1024; // 定义1MB的大小限制
$filename = 'file'.$i;
$ImageName = str_replace(' ','_',strtolower($_FILES[$filename]['name']));
$tmpName = $_FILES[$filename]['tmp_name'];
$originalSize = $_FILES[$filename]['size'];
$fileContent = '';

// 第一步:判断是否为图片文件
$imageInfo = getimagesize($tmpName);
if ($imageInfo !== false) {
    $mime = $imageInfo['mime'];
    $width = $imageInfo[0];
    $height = $imageInfo[1];
    $srcImage = null;

    // 根据图片类型初始化资源
    switch($mime) {
        case 'image/jpeg':
            $srcImage = imagecreatefromjpeg($tmpName);
            break;
        case 'image/png':
            $srcImage = imagecreatefrompng($tmpName);
            imagealphablending($srcImage, true);
            imagesavealpha($srcImage, true); // 保留PNG透明通道
            break;
        case 'image/webp':
            $srcImage = imagecreatefromwebp($tmpName);
            break;
        default:
            // 非支持的图片格式,直接读取原文件
            $fileContent = file_get_contents($tmpName);
            break;
    }

    if ($srcImage) {
        $targetSize = $originalSize;
        $quality = 80; // 初始压缩质量(1-100,越高越清晰)
        $scale = 1.0; // 初始缩放比例

        // 循环调整,直到文件大小符合要求
        while ($targetSize > $maxFileSize && $quality > 10 && $scale > 0.2) {
            // 用内存流计算当前处理后的文件大小
            ob_start();
            if ($mime === 'image/jpeg') {
                imagejpeg($srcImage, null, $quality);
            } elseif ($mime === 'image/png') {
                // PNG的压缩等级是0-9,这里反向映射质量值
                imagepng($srcImage, null, 9 - floor($quality/10));
            } elseif ($mime === 'image/webp') {
                imagewebp($srcImage, null, $quality);
            }
            $fileContent = ob_get_clean();
            $targetSize = strlen($fileContent);

            // 若仍超过限制,先降质量,质量过低再缩尺寸
            if ($targetSize > $maxFileSize) {
                if ($quality > 20) {
                    $quality -= 10; // 每次降低10个质量点
                } else {
                    $scale *= 0.8; // 每次缩小20%
                    $newWidth = floor($width * $scale);
                    $newHeight = floor($height * $scale);
                    $resizedImage = imagecreatetruecolor($newWidth, $newHeight);

                    // 处理PNG透明背景
                    if ($mime === 'image/png') {
                        imagealphablending($resizedImage, false);
                        imagesavealpha($resizedImage, true);
                        $transparent = imagecolorallocatealpha($resizedImage, 255, 255, 255, 127);
                        imagefill($resizedImage, 0, 0, $transparent);
                    }

                    imagecopyresampled($resizedImage, $srcImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
                    imagedestroy($srcImage);
                    $srcImage = $resizedImage;
                    $width = $newWidth;
                    $height = $newHeight;
                }
            }
        }
        imagedestroy($srcImage); // 释放资源
    }
} 
// 第二步:判断是否为PDF文件
else {
    $fileType = mime_content_type($tmpName);
    if ($fileType === 'application/pdf') {
        // 用Ghostscript优化PDF(需服务器安装Ghostscript)
        $tmpOptimizedPdf = tempnam(sys_get_temp_dir(), 'opt_pdf');
        // /screen参数是高压缩率,适合网页展示;可选/ebook /prepress等
        $gsCommand = "gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile=".$tmpOptimizedPdf." ".$tmpName;
        
        exec($gsCommand, $output, $returnStatus);
        if ($returnStatus === 0) {
            $fileContent = file_get_contents($tmpOptimizedPdf);
            // 若优化后仍超1MB,可提示用户或做其他处理
            if (strlen($fileContent) > $maxFileSize) {
                // 这里可以添加错误提示逻辑,比如:
                // die("PDF file is too large even after optimization.");
                $fileContent = file_get_contents($tmpName); // fallback到原文件
            }
            unlink($tmpOptimizedPdf); // 删除临时文件
        } else {
            // Ghostscript执行失败,读取原文件
            $fileContent = file_get_contents($tmpName);
        }
    } 
    // 第三步:其他文件类型,直接读取原文件
    else {
        $fileContent = file_get_contents($tmpName);
    }
}

// 最终检查:若处理后仍超1MB,建议抛出错误(避免损坏文件)
if (strlen($fileContent) > $maxFileSize) {
    die("File size exceeds 1MB limit even after compression. Please upload a smaller file.");
}

// 现在$fileContent就是处理后的内容,可以存入数据库
// 示例:
// $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass');
// $stmt = $pdo->prepare("INSERT INTO files (file_name, file_content) VALUES (?, ?)");
// $stmt->execute([$ImageName, $fileContent]);

三、关键注意事项

  • 图片处理:优先调整压缩质量而非直接缩放,能在保证清晰度的前提下尽量缩小文件;PNG文件要注意保留透明通道,避免出现黑底。
  • PDF处理:Ghostscript是最可靠的PDF压缩工具,若服务器未安装,需要联系运维人员配置;/screen参数的压缩率最高,适合大多数场景。
  • 边界情况:如果处理后文件仍超过1MB,不要强行截断文件,这会导致文件损坏无法打开,建议直接提示用户上传更小的文件。

内容的提问来源于stack exchange,提问作者Masnad Nihit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:11:00