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

如何在上传图片时提取元数据并存入MySQL数据库

实现图片上传时的元数据获取与存储

1. 先更新数据库表结构

首先需要给images表添加存储元数据的字段,执行以下SQL语句:

ALTER TABLE images 
ADD COLUMN camera_model VARCHAR(255) NULL,
ADD COLUMN gps_latitude DECIMAL(10,8) NULL,
ADD COLUMN gps_longitude DECIMAL(11,8) NULL,
ADD COLUMN shoot_period ENUM('day','night') NULL;

2. 改进EXIF元数据读取逻辑

替换原有的getExif函数,改成能批量读取所需元数据的逻辑,同时处理GPS坐标的格式转换:

// 转换EXIF GPS度分秒为十进制坐标
function convertGpsToDecimal($gpsData, $ref) {
    $degrees = $gpsData[0];
    $minutes = $gpsData[1];
    $seconds = $gpsData[2];
    
    $decimal = $degrees + ($minutes / 60) + ($seconds / 3600);
    // 根据参考方向判断正负(南纬、西经为负)
    return ($ref == 'S' || $ref == 'W') ? -$decimal : $decimal;
}

// 获取图片的所有所需元数据
function getImageMetadata($tmpFilePath) {
    $metadata = [
        'camera_model' => '',
        'gps_lat' => null,
        'gps_lng' => null,
        'shoot_period' => 'day'
    ];
    
    $allowedTypes = ['jpg', 'jpeg', 'tif', 'tiff'];
    $fileExt = strtolower(pathinfo($tmpFilePath, PATHINFO_EXTENSION));
    
    if (!in_array($fileExt, $allowedTypes)) {
        return $metadata;
    }
    
    $exif = exif_read_data($tmpFilePath, 0, true);
    if (!$exif) {
        return $metadata;
    }
    
    // 获取相机型号
    if (isset($exif['IFD0']['Model'])) {
        $metadata['camera_model'] = $exif['IFD0']['Model'];
    }
    
    // 获取GPS坐标
    if (isset($exif['GPS']) && isset($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef'], $exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef'])) {
        $metadata['gps_lat'] = convertGpsToDecimal($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']);
        $metadata['gps_lng'] = convertGpsToDecimal($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']);
    }
    
    // 判断拍摄时段(白天/夜晚)
    if (isset($exif['EXIF']['DateTimeOriginal'])) {
        $shootTime = DateTime::createFromFormat('Y:m:d H:i:s', $exif['EXIF']['DateTimeOriginal']);
        if ($shootTime) {
            $hour = $shootTime->format('H');
            $metadata['shoot_period'] = ($hour >= 6 && $hour <= 18) ? 'day' : 'night';
        }
    }
    
    return $metadata;
}

3. 修改上传逻辑,整合元数据存储

修改原有的上传循环部分,使用预处理语句避免SQL注入,同时插入元数据:

foreach($_FILES['files']['name'] as $key=>$val){ 
    // 获取临时文件路径(要在移动文件前读取EXIF,因为移动后临时文件会被销毁)
    $tmpFilePath = $_FILES["files"]["tmp_name"][$key];
    $fileName = basename($_FILES['files']['name'][$key]); 
    $targetFilePath = $targetDir . $fileName; 
    $fileType = pathinfo($targetFilePath, PATHINFO_EXTENSION); 
    
    if(in_array($fileType, $allowTypes)){ 
        // 先读取元数据
        $metadata = getImageMetadata($tmpFilePath);
        // 读取图片宽度(复用原有逻辑)
        $width = getExif($tmpFilePath, "IFD0", "ImageWidth");
        
        // 上传文件到服务器
        if(move_uploaded_file($tmpFilePath, $targetFilePath)){ 
            // 使用预处理语句插入数据,避免SQL注入
            $stmt = $db->prepare("INSERT INTO images(file_name, uploaded_on, image_width, camera_model, gps_latitude, gps_longitude, shoot_period) VALUES (?, NOW(), ?, ?, ?, ?, ?)");
            $stmt->bind_param("sdsdds", $fileName, $width, $metadata['camera_model'], $metadata['gps_lat'], $metadata['gps_lng'], $metadata['shoot_period']);
            $stmt->execute();
            $stmt->close();
        }else{ 
            $errorUpload .= $_FILES['files']['name'][$key].' | '; 
        } 
    }else{ 
        $errorUploadType .= $_FILES['files']['name'][$key].' | '; 
    } 
}

关键注意事项

  • 读取EXIF的时机:必须在move_uploaded_file之前读取临时文件的EXIF,因为文件移动后临时文件会被系统销毁。
  • SQL注入防护:原代码直接拼接SQL存在安全风险,改用预处理语句绑定参数是更安全的做法。
  • 元数据兼容性:不是所有图片都包含完整的EXIF数据,必须做存在性判断,避免触发报错。
  • GPS坐标转换:EXIF中的GPS是度分秒格式,转换为十进制后更方便后续的检索和地图展示。

内容的提问来源于stack exchange,提问作者Tom Meskin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:50:29