video-shuoshan/backend/utils/tos_client.py
seaislee1209 493b30c6b9 fix: source map 禁用 + MD5 改 SHA256
①vite build sourcemap: false,防止源码泄露
②tos_client.py 文件去重哈希从 MD5 改为 SHA256

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:58:52 +08:00

93 lines
2.6 KiB
Python

"""Volcano Engine TOS file upload utility using official TOS SDK."""
import hashlib
import uuid
import logging
from django.conf import settings
logger = logging.getLogger(__name__)
CONTENT_TYPE_MAP = {
'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png',
'webp': 'image/webp', 'gif': 'image/gif', 'bmp': 'image/bmp',
'tiff': 'image/tiff',
'mp4': 'video/mp4', 'mov': 'video/quicktime',
'mp3': 'audio/mpeg', 'wav': 'audio/wav',
}
_client = None
def get_tos_client():
import tos
global _client
if _client is None:
endpoint = settings.TOS_ENDPOINT.replace('https://', '').replace('http://', '')
_client = tos.TosClientV2(
ak=settings.TOS_ACCESS_KEY,
sk=settings.TOS_SECRET_KEY,
endpoint=endpoint,
region=settings.TOS_REGION,
)
return _client
def upload_file(file_obj, folder='uploads'):
"""Upload a file to TOS bucket with content-hash dedup, return its public URL.
Uses MD5 hash of file content as the object key. If the same file
has already been uploaded, the existing URL is returned without
re-uploading, saving storage and bandwidth.
"""
ext = file_obj.name.rsplit('.', 1)[-1].lower()
content_type = CONTENT_TYPE_MAP.get(ext, 'application/octet-stream')
client = get_tos_client()
content = file_obj.read()
# Use content hash as key for dedup
content_hash = hashlib.sha256(content).hexdigest()
key = f'{folder}/{content_hash}.{ext}'
url = f'{settings.TOS_CDN_DOMAIN}/{key}'
# Check if object already exists — skip upload if so
try:
client.head_object(bucket=settings.TOS_BUCKET, key=key)
logger.info('TOS dedup hit: %s', key)
return url
except Exception:
pass # Object doesn't exist, proceed with upload
client.put_object(
bucket=settings.TOS_BUCKET,
key=key,
content=content,
content_type=content_type,
)
return url
def upload_from_url(source_url, folder='results'):
"""Download a file from a URL and upload to TOS, return permanent CDN URL."""
import requests as req
resp = req.get(source_url, timeout=120, stream=True)
resp.raise_for_status()
content = resp.content
content_type = resp.headers.get('Content-Type', 'video/mp4')
ext = 'mp4' # Seedance always returns mp4
key = f'{folder}/{uuid.uuid4().hex}.{ext}'
client = get_tos_client()
client.put_object(
bucket=settings.TOS_BUCKET,
key=key,
content=content,
content_type=content_type,
)
return f'{settings.TOS_CDN_DOMAIN}/{key}'