update checkin image issue

This commit is contained in:
2025-09-03 07:56:40 +09:00
parent 4901b44f4a
commit a0e024b77d
5 changed files with 260 additions and 15 deletions

1
rog/utils/__init__.py Normal file
View File

@ -0,0 +1 @@
# Python package marker

View File

@ -0,0 +1,153 @@
"""
S3画像アップロードユーティリティ
チェックイン時の画像をS3にアップロードし、URLを生成します
"""
import boto3
import logging
import uuid
from datetime import datetime
from django.conf import settings
from botocore.exceptions import ClientError, NoCredentialsError
import base64
import io
import requests
logger = logging.getLogger(__name__)
class S3ImageUploader:
def __init__(self):
"""S3クライアントを初期化"""
try:
self.s3_client = boto3.client(
's3',
aws_access_key_id=getattr(settings, 'AWS_ACCESS_KEY', None),
aws_secret_access_key=getattr(settings, 'AWS_SECRET_ACCESS_KEY', None),
region_name=getattr(settings, 'AWS_REGION', 'us-west-2')
)
self.bucket_name = getattr(settings, 'S3_BUCKET_NAME', 'sumasenrogaining')
logger.info(f"S3 client initialized for bucket: {self.bucket_name}")
except Exception as e:
logger.error(f"Failed to initialize S3 client: {e}")
self.s3_client = None
self.bucket_name = None
def upload_checkin_image(self, image_data, event_code, zekken_number, cp_number):
"""
チェックイン画像をS3にアップロード
Args:
image_data: 画像データURLまたはBase64
event_code: イベントコード
zekken_number: ゼッケン番号
cp_number: チェックポイント番号
Returns:
str: S3のURL、失敗時は元のimage_data
"""
if not self.s3_client or not image_data:
logger.warning("S3 client not available or no image data, returning original")
return image_data
try:
# 画像データを取得
image_binary = self._get_image_binary(image_data)
if not image_binary:
logger.error("Failed to get image binary data, returning original")
return image_data
# S3キーを生成: {event_code}/{zekken_number}/{cp_number}.jpg
s3_key = f"{event_code}/{zekken_number}/{cp_number}.jpg"
# S3にアップロード
self.s3_client.put_object(
Bucket=self.bucket_name,
Key=s3_key,
Body=image_binary,
ContentType='image/jpeg',
ACL='public-read' # 公開読み取り可能
)
# S3 URLを生成
aws_region = getattr(settings, 'AWS_REGION', 'us-west-2')
s3_url = f"https://{self.bucket_name}.s3.{aws_region}.amazonaws.com/{s3_key}"
logger.info(f"Successfully uploaded image to S3: {s3_url}")
return s3_url
except ClientError as e:
logger.error(f"S3 upload failed: {e}, returning original URL")
return image_data
except Exception as e:
logger.error(f"Unexpected error during S3 upload: {e}, returning original URL")
return image_data
def _get_image_binary(self, image_data):
"""
画像データからバイナリデータを取得
Args:
image_data: 画像URLHTTPまたはBase64エンコードされた画像データ
Returns:
bytes: 画像のバイナリデータ
"""
try:
if isinstance(image_data, str):
# HTTPURLの場合
if image_data.startswith('http'):
return self._download_image_from_url(image_data)
# Base64の場合
elif self._is_base64(image_data):
return base64.b64decode(image_data)
# data:image/jpeg;base64,の形式の場合
elif image_data.startswith('data:image'):
base64_data = image_data.split(',')[1]
return base64.b64decode(base64_data)
logger.error(f"Unsupported image data format: {type(image_data)}")
return None
except Exception as e:
logger.error(f"Error processing image data: {e}")
return None
def _download_image_from_url(self, url):
"""URLから画像をダウンロード"""
try:
response = requests.get(url, timeout=30)
response.raise_for_status()
return response.content
except Exception as e:
logger.error(f"Failed to download image from URL {url}: {e}")
return None
def _is_base64(self, data):
"""文字列がBase64かどうかをチェック"""
try:
if isinstance(data, str):
base64.b64decode(data, validate=True)
return True
except Exception:
return False
return False
def generate_s3_url(self, event_code, zekken_number, cp_number):
"""
S3 URLを生成アップロード済みの画像用
Args:
event_code: イベントコード
zekken_number: ゼッケン番号
cp_number: チェックポイント番号
Returns:
str: S3のURL
"""
aws_region = getattr(settings, 'AWS_REGION', 'us-west-2')
s3_key = f"{event_code}/{zekken_number}/{cp_number}.jpg"
return f"https://{self.bucket_name}.s3.{aws_region}.amazonaws.com/{s3_key}"
# グローバルインスタンス
s3_uploader = S3ImageUploader()