上一篇
想象一下,你正在开发一个电商平台的后台管理系统,每天商家都会上传大量商品图片,你需要将这些图片妥善保存到服务器,同时还要提供下载功能以便商家能够备份或修改,这就是我们今天要解决的典型场景——使用PHP实现图片的保存与下载功能。
<?php // 检查是否有文件上传 if(isset($_FILES['image'])) { $uploadDir = 'uploads/images/'; // 上传目录 $fileName = basename($_FILES['image']['name']); // 原始文件名 $filePath = $uploadDir . $fileName; // 完整路径 // 检查目录是否存在,不存在则创建 if (!file_exists($uploadDir)) { mkdir($uploadDir, 0777, true); } // 移动临时文件到目标位置 if(move_uploaded_file($_FILES['image']['tmp_name'], $filePath)) { echo "图片上传成功!保存路径:".$filePath; } else { echo "图片上传失败!"; } } ?>
<?php if(isset($_FILES['image'])) { $uploadDir = 'uploads/images/'; // 生成唯一文件名,防止覆盖 $fileExt = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION); $fileName = uniqid().'.'.$fileExt; $filePath = $uploadDir . $fileName; // 允许的图片类型 $allowedTypes = ['image/jpeg', 'image/png', 'image/gif']; // 检查文件类型 if(!in_array($_FILES['image']['type'], $allowedTypes)) { die("错误:只允许上传JPEG, PNG和GIF图片"); } // 检查文件大小(限制为2MB) if($_FILES['image']['size'] > 2000000) { die("错误:图片大小不能超过2MB"); } // 使用GD库验证确实是图片 if(!getimagesize($_FILES['image']['tmp_name'])) { die("错误:上传的文件不是有效图片"); } // 移动文件 if(move_uploaded_file($_FILES['image']['tmp_name'], $filePath)) { // 添加水印(可选) addWatermark($filePath); echo "图片上传成功!"; } else { echo "图片上传失败!"; } } // 添加水印函数 function addWatermark($imagePath) { // 根据图片类型创建资源 $imageInfo = getimagesize($imagePath); switch($imageInfo['mime']) { case 'image/jpeg': $image = imagecreatefromjpeg($imagePath); break; case 'image/png': $image = imagecreatefrompng($imagePath); break; case 'image/gif': $image = imagecreatefromgif($imagePath); break; default: return; } // 设置水印文字颜色 $textColor = imagecolorallocate($image, 255, 255, 255); // 添加水印文字 imagestring($image, 5, 10, 10, 'MyShop 2025', $textColor); // 保存图片 switch($imageInfo['mime']) { case 'image/jpeg': imagejpeg($image, $imagePath); break; case 'image/png': imagepng($image, $imagePath); break; case 'image/gif': imagegif($image, $imagePath); break; } // 释放内存 imagedestroy($image); } ?>
<?php // 要下载的文件路径 $filePath = 'uploads/images/product123.jpg'; // 检查文件是否存在 if(file_exists($filePath)) { // 获取文件信息 $fileName = basename($filePath); $fileSize = filesize($filePath); // 设置HTTP头 header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=".$fileName); header("Content-Length: ".$fileSize); // 读取文件并输出到浏览器 readfile($filePath); exit; } else { echo "文件不存在!"; } ?>
<?php $filePath = 'uploads/images/large_product_image.jpg'; if(file_exists($filePath)) { $fileName = basename($filePath); $fileSize = filesize($filePath); $fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION)); // 根据扩展名设置正确的Content-Type $contentTypes = [ 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif' ]; $contentType = isset($contentTypes[$fileExt]) ? $contentTypes[$fileExt] : 'application/octet-stream'; // 处理断点续传 $range = 0; if(isset($_SERVER['HTTP_RANGE'])) { list($sizeUnit, $rangeOrig) = explode('=', $_SERVER['HTTP_RANGE'], 2); if($sizeUnit == 'bytes') { list($range, $extra) = explode('-', $rangeOrig, 2); $range = intval($range); } } // 设置HTTP头 header("Content-Type: ".$contentType); header("Accept-Ranges: bytes"); if($range > 0) { // 断点续传 header("HTTP/1.1 206 Partial Content"); header("Content-Range: bytes $range-".($fileSize-1)."/$fileSize"); header("Content-Length: ".($fileSize - $range)); } else { // 普通下载 header("Content-Disposition: attachment; filename=".$fileName); header("Content-Length: $fileSize"); } // 打开文件并发送内容 $file = fopen($filePath, 'rb'); if($range > 0) { fseek($file, $range); } while(!feof($file)) { print(fread($file, 8192)); flush(); } fclose($file); exit; } else { http_response_code(404); echo "文件不存在!"; } ?>
function compressImage($sourcePath, $targetPath, $quality = 75) { $imageInfo = getimagesize($sourcePath); switch($imageInfo['mime']) { case 'image/jpeg': $image = imagecreatefromjpeg($sourcePath); break; case 'image/png': $image = imagecreatefrompng($sourcePath); // PNG压缩级别 (0-9) $quality = 9 - round(($quality * 9) / 100); break; case 'image/gif': $image = imagecreatefromgif($sourcePath); break; default: return false; } // 保存压缩后的图片 switch($imageInfo['mime']) { case 'image/jpeg': $result = imagejpeg($image, $targetPath, $quality); break; case 'image/png': $result = imagepng($image, $targetPath, $quality); break; case 'image/gif': $result = imagegif($image, $targetPath); break; } imagedestroy($image); return $result; }
function createThumbnail($sourcePath, $targetPath, $thumbWidth = 200) { $imageInfo = getimagesize($sourcePath); // 根据图片类型创建资源 switch($imageInfo['mime']) { case 'image/jpeg': $sourceImage = imagecreatefromjpeg($sourcePath); break; case 'image/png': $sourceImage = imagecreatefrompng($sourcePath); break; case 'image/gif': $sourceImage = imagecreatefromgif($sourcePath); break; default: return false; } // 获取原始尺寸 $width = imagesx($sourceImage); $height = imagesy($sourceImage); // 计算缩略图高度(保持比例) $thumbHeight = floor($height * ($thumbWidth / $width)); // 创建缩略图画布 $thumbnail = imagecreatetruecolor($thumbWidth, $thumbHeight); // 透明背景处理(PNG/GIF) if($imageInfo['mime'] == 'image/png' || $imageInfo['mime'] == 'image/gif') { imagecolortransparent($thumbnail, imagecolorallocatealpha($thumbnail, 0, 0, 0, 127)); imagealphablending($thumbnail, false); imagesavealpha($thumbnail, true); } // 复制并调整大小 imagecopyresampled($thumbnail, $sourceImage, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height); // 保存缩略图 switch($imageInfo['mime']) { case 'image/jpeg': $result = imagejpeg($thumbnail, $targetPath, 90); break; case 'image/png': $result = imagepng($thumbnail, $targetPath, 9); break; case 'image/gif': $result = imagegif($thumbnail, $targetPath); break; } // 释放内存 imagedestroy($sourceImage); imagedestroy($thumbnail); return $result; }
function getImageList($directory) { $images = []; $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif']; // 检查目录是否存在 if(!is_dir($directory)) { return $images; } // 打开目录 if($handle = opendir($directory)) { while(false !== ($entry = readdir($handle))) { if($entry != "." && $entry != "..") { $extension = strtolower(pathinfo($entry, PATHINFO_EXTENSION)); if(in_array($extension, $allowedExtensions)) { $filePath = $directory . '/' . $entry; $fileSize = filesize($filePath); $fileDate = date("Y-m-d H:i:s", filemtime($filePath)); $images[] = [ 'name' => $entry, 'path' => $filePath, 'size' => formatFileSize($fileSize), 'date' => $fileDate, 'dimensions' => getImageDimensions($filePath) ]; } } } closedir($handle); } return $images; } // 辅助函数:格式化文件大小 function formatFileSize($bytes) { if($bytes >= 1073741824) { return number_format($bytes / 1073741824, 2) . ' GB'; } elseif($bytes >= 1048576) { return number_format($bytes / 1048576, 2) . ' MB'; } elseif($bytes >= 1024) { return number_format($bytes / 1024, 2) . ' KB'; } else { return $bytes . ' bytes'; } } // 辅助函数:获取图片尺寸 function getImageDimensions($filePath) { $dimensions = getimagesize($filePath); return $dimensions[0].'x'.$dimensions[1]; }
function batchProcessImages($directory, $callback) { $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif']; if(!is_dir($directory)) { return false; } $results = []; if($handle = opendir($directory)) { while(false !== ($entry = readdir($handle))) { if($entry != "." && $entry != "..") { $extension = strtolower(pathinfo($entry, PATHINFO_EXTENSION)); if(in_array($extension, $allowedExtensions)) { $filePath = $directory . '/' . $entry; $results[] = call_user_func($callback, $filePath); } } } closedir($handle); } return $results; } // 使用示例:批量生成缩略图 $thumbnailDir = 'uploads/thumbnails/'; if(!file_exists($thumbnailDir)) { mkdir($thumbnailDir, 0777, true); } batchProcessImages('uploads/images/', function($filePath) use ($thumbnailDir) { $fileName = basename($filePath); $thumbnailPath = $thumbnailDir . 'thumb_' . $fileName; return createThumbnail($filePath, $thumbnailPath); });
文件上传验证:始终验证上传文件的类型、大小和内容,不要仅依赖文件扩展名
目录权限:上传目录不应有执行权限,通常设置为755或更严格
文件名处理:避免使用用户提供的原始文件名,防止目录遍历攻击
内存管理:处理大图片时注意内存限制,考虑使用流式处理
错误处理:在生产环境中不要显示详细的错误信息
定期清理:设置定时任务清理长时间未使用的临时文件
缓存缩略图:不要每次请求都重新生成缩略图
使用CDN:对于高流量网站,考虑使用CDN分发图片
延迟加载:对页面上的图片实现延迟加载技术
图片格式选择:根据场景选择最合适的图片格式(WebP通常是最佳选择)
批量处理:对大量图片操作使用队列系统异步处理
通过本文的学习,你应该已经掌握了使用PHP处理图片上传、下载以及本地文件管理的基本方法和高级技巧,这些技术可以广泛应用于内容管理系统、电商平台、社交网络等各种需要处理用户上传图片的场景,良好的图片处理系统不仅要功能完善,还要注重安全性和性能优化。
本文由 连梦玉 于2025-08-02发表在【云服务器提供商】,文中图片由(连梦玉)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/512455.html
发表评论