python 使用fastapi 和 Pillow 获取图片的exif信息

from fastapi import APIRouter, File, UploadFile
from typing import List
import shutil
import os

from PIL import Image, ExifTags
from PIL.ExifTags import TAGS

import io

router = APIRouter()

@router.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
    exif_data = await get_exif_data(file)

    useful_exif = {}
    useful_exif['DateTime']=exif_data['DateTime']
    useful_exif['lat']=exif_data['lat']
    useful_exif['lon']=exif_data['lon']

    return {"useful_exif": useful_exif}


async def get_exif_data(file):
    # 读取上传的文件内容
    contents = await file.read()
    # 将文件内容转换为 PIL.Image 对象
    image = Image.open(io.BytesIO(contents))

    # 获取 EXIF 数据
    exif_data = image._getexif()

    if exif_data is None:
        print("图片中没有 EXIF 数据")
        return None

    # 解析 EXIF 数据
    parsed_exif = {}
    for tag, value in exif_data.items():
        tag_name = TAGS.get(tag, tag)  # 将标签 ID 转换为标签名称

        if isinstance(value, bytes):
            try:
                value = value.decode('utf-8')
            except UnicodeDecodeError:
                value = "Binary data (not decoded)"
        #if tag_name == "GPSInfo":
                #    for t in value:
                #        gps_tag = ExifTags.GPSTAGS.get(t, t)
        #        parsed_exif[gps_tag] = value[t]
        #else:
        #    parsed_exif[tag_name] = value

        parsed_exif[tag_name] = value

    print(parsed_exif)

    gps_info = get_gps_info(parsed_exif)
    if gps_info:
        latitude, longitude = get_lat_lon(gps_info)
        if latitude and longitude:
            parsed_exif['lat'] = float(latitude)
            parsed_exif['lon'] = float(longitude)
    return parsed_exif

def get_gps_info(exif_data):
    if not exif_data:
        return None

    for tag_id, value in exif_data.items():
        tag_name = TAGS.get(tag_id, tag_id)
        if tag_name == "GPSInfo":
            return value
    return None

def convert_to_decimal(gps_tuple):
    degrees, minutes, seconds = gps_tuple
    decimal = degrees + (minutes / 60) + (seconds / 3600)
    return decimal

def get_lat_lon(gps_info):
    if not gps_info:
        return None, None

    lat_tuple = gps_info.get(2)  # 纬度
    lon_tuple = gps_info.get(4)  # 经度

    if not lat_tuple or not lon_tuple:
        return None, None

    lat = convert_to_decimal(lat_tuple)
    lon = convert_to_decimal(lon_tuple)

    if gps_info.get(1) == "S":
        lat = -lat
    if gps_info.get(3) == "W":
        lon = -lon

    return lat, lon

这里如果使用Apifox接口测试工具,可能会报错

Expected boundary character 45, got 0 at index 2

用curl 请求没这个问题 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值