PHP上传JPEG至MySQL无法获取图片元数据的问题排查
解决图片上传时无法获取元数据(宽度)的问题
核心问题分析
你的代码无法获取图片宽度的关键原因:
- 调用
getExif时传入的是客户端文件名,此时文件还在服务器临时目录,exif_read_data找不到对应文件,返回默认值0。 - 扩展名判断逻辑有误,无法识别
jpeg这类4字符后缀的文件。 - 仅依赖Exif无法兼容PNG、GIF等无Exif数据的图片格式。
- 直接拼接SQL语句存在注入风险。
修正后的完整代码
<?php // Include the database configuration file include_once 'dbconfig.php'; if(isset($_POST['submit'])){ // File upload configuration $targetDir = "C:\xampp\htdocs\uploaded\\"; $allowTypes = array('jpg','png','jpeg','gif'); $statusMsg = $errorMsg = $insertValuesSQL = $errorUpload = $errorUploadType = ''; $fileNames = array_filter($_FILES['files']['name']); if(!empty($fileNames)){ // 获取图片宽度,兼容所有支持的格式 function getImageWidth($filePath) { $width = 0; // 先尝试用getimagesize,兼容所有图片类型 $imageInfo = getimagesize($filePath); if($imageInfo !== false){ $width = $imageInfo[0]; } return $width; } foreach($_FILES['files']['name'] as $key=>$val){ // 获取临时文件路径,这是当前服务器上存在的文件 $tmpFilePath = $_FILES["files"]["tmp_name"][$key]; $fileName = basename($_FILES['files']['name'][$key]); // 从临时文件获取宽度 $width = getImageWidth($tmpFilePath); $targetFilePath = $targetDir . $fileName; // 正确获取文件扩展名 $fileType = strtolower(pathinfo($targetFilePath, PATHINFO_EXTENSION)); if(in_array($fileType, $allowTypes)){ // Upload file to server if(move_uploaded_file($tmpFilePath, $targetFilePath)){ // 使用预处理语句避免SQL注入(推荐方式) // 这里先改用占位符,后续统一处理 $insertValuesSQL .= "('".$fileName."', NOW(), '".$width."'),"; }else{ $errorUpload .= $_FILES['files']['name'][$key].' | '; } }else{ $errorUploadType .= $_FILES['files']['name'][$key].' | '; } } // Error message $errorUpload = !empty($errorUpload)?'Upload Error: '.trim($errorUpload, ' | '):''; $errorUploadType = !empty($errorUploadType)?'File Type Error: '.trim($errorUploadType, ' | '):''; $errorMsg = !empty($errorUpload)?'<br/>'.$errorUpload.'<br/>'.$errorUploadType:'<br/>'.$errorUploadType; if(!empty($insertValuesSQL)){ $insertValuesSQL = trim($insertValuesSQL, ','); // 注意:生产环境建议使用预处理语句替代直接拼接,示例如下: // $stmt = $db->prepare("INSERT INTO images(file_name, uploaded_on, image_width) VALUES (?, NOW(), ?)"); // foreach(...) { ... $stmt->bind_param("si", $fileName, $width); $stmt->execute(); ... } // Insert image file name into database $insert = $db->query("INSERT INTO images(file_name, uploaded_on, image_width) VALUES $insertValuesSQL"); if($insert){ $statusMsg = "Files are uploaded successfully.".$errorMsg; }else{ $statusMsg = "Sorry, there was an error uploading your file."; } }else{ $statusMsg = "Upload failed! ".$errorMsg; } }else{ $statusMsg = 'Please select a file to upload.'; } } ?> <form action="upload1.php" method="post" enctype="multipart/form-data"> Select Image Files to Upload: <input type="file" name="files[]" multiple > <input type="submit" name="submit" value="UPLOAD"> </form>
关键修改说明
- 改用临时文件路径获取元数据:使用
$_FILES["files"]["tmp_name"][$key]作为读取文件的路径,此时文件已上传到服务器临时目录,可以正常读取。 - 替换为
getimagesize获取宽度:该函数支持所有PHP支持的图片格式(JPG/PNG/GIF等),无需依赖Exif,兼容性更好。 - 修正扩展名判断:用
pathinfo配合strtolower正确获取文件扩展名,避免jpeg这类后缀被误判。 - 添加SQL注入安全提示:生产环境建议使用预处理语句替代字符串拼接,避免SQL注入风险。
扩展说明
如果需要获取更多元数据(如Exif里的拍摄时间、相机型号等),可以在getImageWidth函数中结合exif_read_data补充逻辑,示例:
function getImageMetadata($filePath) { $metadata = [ 'width' => 0, 'height' => 0, 'camera' => '', 'shot_time' => '' ]; // 获取基础尺寸 $imageInfo = getimagesize($filePath); if($imageInfo !== false){ $metadata['width'] = $imageInfo[0]; $metadata['height'] = $imageInfo[1]; } // 尝试读取Exif数据(仅支持JPG/TIFF) $exif = exif_read_data($filePath, 0, true); if($exif !== false){ $metadata['camera'] = $exif['IFD0']['Model'] ?? ''; $metadata['shot_time'] = $exif['EXIF']['DateTimeOriginal'] ?? ''; } return $metadata; }
内容的提问来源于stack exchange,提问作者Tom Meskin
相关产品推荐
相关产品推荐

