如何在PHP中获取Instagram已发布帖子的元数据与EXIF信息
在PHP中获取Instagram帖子的EXIF元数据并检测多帧图像
一、目标获取的EXIF元数据
以下是需要从Instagram帖子图片中提取的完整元数据:
- file_name: 378996423_1583432815397894_4604468632574713944_n.jpg
- file_size: 345 kB
- file_type: JPEG
- file_type_extension: jpg
- mime_type: image/jpeg
- jfif_version: 1.01
- resolution_unit: None
- x_resolution: 72
- y_resolution: 72
- xmp_toolkit: Adobe XMP Core 5.1.2
- version: 1
- directory_item_semantic: Primary
- directory_item_mime: image/jpeg
- directory_item_length: 54828
- mpf_version: 100
- number_of_images: 2
- mp_image_flags: (none)
- mp_image_format: JPEG
- mp_image_type: Undefined
- mp_image_length: 54828
- mp_image_start: 289682
- dependent_image1_entry_number: 0
- dependent_image2_entry_number: 0
- image_width: 1440
- image_height: 1800
- encoding_process: Baseline DCT, Huffman coding
- bits_per_sample: 8
- color_components: 3
- y_cb_cr_sub_sampling: YCbCr4:2:0 (2 2)
- image_size: 1440x1800
- megapixels: 2.6
- mp_image2: (Binary data 54828 bytes)
- category: image
二、现有S3上传函数
public static function uploadFileToS3($fileUrl, $resize = true) { try { $data['status'] = false; $fileFromUrl = parse_url($fileUrl); $fileExt = pathinfo($fileFromUrl['path'], PATHINFO_EXTENSION); $filePath = config('constants.fileStorePath.uploaded') . getCustomEnv('APP_ENV') . '/' . 'intagrams/'; $uniqueName = date('YmdHis') . '_' . uniqid() . '.' . $fileExt; $fileNameWithPath = $filePath . $uniqueName; if (!file_exists(public_path($filePath))) { \File::makeDirectory(public_path($filePath), 0777, true, true); } // HEIC格式不支持,转为JPEG Log::debug("THIS IS FILE EXTENTION".print_r($fileExt,TRUE)); if ($fileExt == 'heic') { $fileExt = 'jpeg'; } if ($resize) { $resizedImage = Image::make($fileUrl)->resize(CmnEnum::GOOGLE_GMB_RECM_RES_SQUARE, CmnEnum::GOOGLE_GMB_RECM_RES_SQUARE)->encode($fileExt); $resizedImage->exif(); $result = Storage::disk('s3')->put($fileNameWithPath, $resizedImage->__toString(), CmnEnum::AWS_S3_VISIBILITY_PUBLIC); } else { $result = Storage::disk('s3')->put($fileNameWithPath, Image::make($fileUrl)->encode($fileExt)->__toString(), CmnEnum::AWS_S3_VISIBILITY_PUBLIC); } if ($result) { $data['status'] = true; $data['fileNameWithPath'] = $fileNameWithPath; return $data; } Log::error("Image is not uploaded in s3"); return $data; } catch (\Exception $e) { $data['status'] = false; writeCustomLog($e); Log::error("Image uploading to s3 failed"); return $data; } }
三、需求说明
- 从Instagram帖子链接(
$fileUrl)中提取上述全部EXIF元数据 - 检测图片是否为多帧格式(对应元数据中的
number_of_images = 2) - 服务器无法安装ImageMagick,只能依赖GD扩展或Intervention Image的GD驱动
四、修改后的实现方案
核心思路
- 使用PHP原生
exif_read_data()函数读取完整EXIF元数据(需开启exif扩展) - 通过MPF区段的
NumberOfImages字段检测多帧图像 - 利用临时文件处理远程图片的EXIF读取
- 保留Intervention Image处理时的EXIF信息(可选)
修改后的完整函数
public static function uploadFileToS3($fileUrl, $resize = true) { try { $data['status'] = false; $fileFromUrl = parse_url($fileUrl); $fileExt = pathinfo($fileFromUrl['path'], PATHINFO_EXTENSION); // 下载远程图片到临时文件,用于读取EXIF $tempFile = tempnam(sys_get_temp_dir(), 'ig_'); if (!@file_put_contents($tempFile, file_get_contents($fileUrl))) { Log::error("Failed to download image from URL: " . $fileUrl); unlink($tempFile); return $data; } // 读取全量EXIF元数据,指定读取MPF区段以获取多帧信息 $exifData = exif_read_data($tempFile, 'EXIF,MPF,IFD0,IFD1,JFIF,XMP', true); // 检测多帧图像 $data['has_multiple_images'] = isset($exifData['MPF']['NumberOfImages']) && $exifData['MPF']['NumberOfImages'] > 1; // 将提取的EXIF元数据加入返回结果 $data['exif_metadata'] = $exifData; $filePath = config('constants.fileStorePath.uploaded') . getCustomEnv('APP_ENV') . '/' . 'intagrams/'; $uniqueName = date('YmdHis') . '_' . uniqid() . '.' . $fileExt; $fileNameWithPath = $filePath . $uniqueName; if (!file_exists(public_path($filePath))) { \File::makeDirectory(public_path($filePath), 0777, true, true); } // HEIC格式转JPEG if ($fileExt == 'heic') { $fileExt = 'jpeg'; } if ($resize) { $resizedImage = Image::make($fileUrl) ->resize(CmnEnum::GOOGLE_GMB_RECM_RES_SQUARE, CmnEnum::GOOGLE_GMB_RECM_RES_SQUARE) ->preserveExif() // 保留EXIF信息上传到S3 ->encode($fileExt); $result = Storage::disk('s3')->put($fileNameWithPath, $resizedImage->__toString(), CmnEnum::AWS_S3_VISIBILITY_PUBLIC); } else { $image = Image::make($fileUrl) ->preserveExif() // 保留EXIF信息上传到S3 ->encode($fileExt); $result = Storage::disk('s3')->put($fileNameWithPath, $image->__toString(), CmnEnum::AWS_S3_VISIBILITY_PUBLIC); } // 清理临时文件 unlink($tempFile); if ($result) { $data['status'] = true; $data['fileNameWithPath'] = $fileNameWithPath; return $data; } Log::error("Image is not uploaded in s3"); return $data; } catch (\Exception $e) { $data['status'] = false; writeCustomLog($e); Log::error("Image uploading to s3 failed"); return $data; } }
注意事项
- 开启EXIF扩展:确保php.ini中启用
extension=exif,并且allow_url_fopen为On(用于远程图片下载) - EXIF键名对应:原生函数返回的键名可能与在线查看器略有差异,例如
number_of_images对应$exifData['MPF']['NumberOfImages'] - 临时文件清理:使用
tempnam创建临时文件,处理完成后必须用unlink删除,避免磁盘占用 - Intervention Image配置:如果未安装ImageMagick,Intervention Image会自动使用GD驱动,无需额外配置
- 错误处理:新增了远程图片下载失败的捕获逻辑,避免后续流程报错
内容的提问来源于stack exchange,提问作者Shafin Junayed
相关产品推荐
相关产品推荐

