feat: 图片存储改为阿里云OSS
This commit is contained in:
parent
74efe2d543
commit
c0bd161fb7
|
|
@ -14,10 +14,36 @@ router = APIRouter(prefix="/api/ocr", tags=["OCR 识别"])
|
||||||
# 阿里云 DashScope API 配置
|
# 阿里云 DashScope API 配置
|
||||||
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY", "sk-9389024a37da4f7bb455ac9a6b28776f")
|
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY", "sk-9389024a37da4f7bb455ac9a6b28776f")
|
||||||
|
|
||||||
# 上传目录配置
|
# 阿里云 OSS 配置
|
||||||
|
OSS_CONFIG = {
|
||||||
|
"access_key_id": os.getenv("OSS_ACCESS_KEY_ID", "LTAI5t6HUnpFBLEK9194kPVG"),
|
||||||
|
"access_key_secret": os.getenv("OSS_ACCESS_KEY_SECRET", "LEr4Q8yRxb8D5b24cKfCwlt4MMoke1"),
|
||||||
|
"bucket_name": "jiachenlong-oss",
|
||||||
|
"endpoint": "oss-cn-hangzhou.aliyuncs.com",
|
||||||
|
"public_url": "https://jiachenlong-oss.oss-cn-hangzhou.aliyuncs.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 临时上传目录(用于OCR识别)
|
||||||
UPLOAD_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads", "temp")
|
UPLOAD_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads", "temp")
|
||||||
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def upload_to_oss(file_data, filename, bucket_name=None):
|
||||||
|
"""上传文件到阿里云OSS"""
|
||||||
|
import oss2
|
||||||
|
bucket_name = bucket_name or OSS_CONFIG["bucket_name"]
|
||||||
|
|
||||||
|
auth = oss2.Auth(OSS_CONFIG["access_key_id"], OSS_CONFIG["access_key_secret"])
|
||||||
|
bucket = oss2.Bucket(auth, OSS_CONFIG["endpoint"], bucket_name)
|
||||||
|
|
||||||
|
# 上传文件
|
||||||
|
result = bucket.put_object(filename, file_data)
|
||||||
|
|
||||||
|
if result.status == 200:
|
||||||
|
return f"{OSS_CONFIG['public_url']}/{filename}"
|
||||||
|
else:
|
||||||
|
raise Exception(f"OSS上传失败: {result.status}")
|
||||||
|
|
||||||
# 专业提示词
|
# 专业提示词
|
||||||
PROFESSIONAL_PROMPT = """你是一名专业的人民币生肖纪念钞鉴定专家。请严格按照以下步骤分析这张图片,并提取准确信息。
|
PROFESSIONAL_PROMPT = """你是一名专业的人民币生肖纪念钞鉴定专家。请严格按照以下步骤分析这张图片,并提取准确信息。
|
||||||
|
|
||||||
|
|
@ -62,15 +88,21 @@ async def recognize_image(
|
||||||
image_data = await image.read()
|
image_data = await image.read()
|
||||||
image_base64 = base64.b64encode(image_data).decode('utf-8')
|
image_base64 = base64.b64encode(image_data).decode('utf-8')
|
||||||
|
|
||||||
# 生成临时文件名(识别后保存到服务器)
|
# 生成临时文件名(识别后保存到OSS)
|
||||||
temp_id = str(uuid.uuid4())
|
temp_id = str(uuid.uuid4())
|
||||||
ext = image.filename.split('.')[-1] if '.' in image.filename else 'jpg'
|
ext = image.filename.split('.')[-1] if '.' in image.filename else 'jpg'
|
||||||
|
oss_key = f"temp/{temp_id}.{ext}"
|
||||||
|
|
||||||
|
# 上传到OSS
|
||||||
|
try:
|
||||||
|
image_url = upload_to_oss(image_data, oss_key)
|
||||||
|
except Exception as oss_err:
|
||||||
|
# OSS失败时保存到本地作为备选
|
||||||
temp_filename = f"{temp_id}.{ext}"
|
temp_filename = f"{temp_id}.{ext}"
|
||||||
temp_path = os.path.join(UPLOAD_DIR, temp_filename)
|
temp_path = os.path.join(UPLOAD_DIR, temp_filename)
|
||||||
|
|
||||||
# 保存图片到临时目录
|
|
||||||
with open(temp_path, 'wb') as f:
|
with open(temp_path, 'wb') as f:
|
||||||
f.write(image_data)
|
f.write(image_data)
|
||||||
|
image_url = f"/uploads/temp/{temp_filename}"
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Bearer {DASHSCOPE_API_KEY}",
|
"Authorization": f"Bearer {DASHSCOPE_API_KEY}",
|
||||||
|
|
@ -130,9 +162,10 @@ async def recognize_image(
|
||||||
"fields": fields,
|
"fields": fields,
|
||||||
"temp_image": {
|
"temp_image": {
|
||||||
"id": temp_id,
|
"id": temp_id,
|
||||||
"filename": temp_filename,
|
"filename": oss_key.split('/')[-1],
|
||||||
"path": f"uploads/temp/{temp_filename}",
|
"path": image_url,
|
||||||
"original_name": image.filename
|
"original_name": image.filename,
|
||||||
|
"is_oss": image_url.startswith("https://")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,9 +254,8 @@ async def claim_temp_image(
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
db: Session = Depends(get_db)
|
db: Session = Depends(get_db)
|
||||||
):
|
):
|
||||||
"""将临时图片移动到藏品目录"""
|
"""将临时图片移动到正式藏品目录"""
|
||||||
from app.models.models import Collection, CollectionImage
|
from app.models.models import Collection, CollectionImage
|
||||||
import shutil
|
|
||||||
|
|
||||||
# 验证藏品是否存在
|
# 验证藏品是否存在
|
||||||
collection = db.query(Collection).filter(
|
collection = db.query(Collection).filter(
|
||||||
|
|
@ -234,49 +266,71 @@ async def claim_temp_image(
|
||||||
if not collection:
|
if not collection:
|
||||||
raise HTTPException(status_code=404, detail="藏品不存在")
|
raise HTTPException(status_code=404, detail="藏品不存在")
|
||||||
|
|
||||||
# 临时文件路径
|
# 生成正式文件名
|
||||||
temp_filename = f"{temp_id}.jpg"
|
|
||||||
temp_path = os.path.join(UPLOAD_DIR, temp_filename)
|
|
||||||
|
|
||||||
# 检查临时文件是否存在
|
|
||||||
if not os.path.exists(temp_path):
|
|
||||||
# 尝试其他扩展名
|
|
||||||
for ext in ['jpeg', 'png', 'gif']:
|
|
||||||
temp_filename = f"{temp_id}.{ext}"
|
|
||||||
temp_path = os.path.join(UPLOAD_DIR, temp_filename)
|
|
||||||
if os.path.exists(temp_path):
|
|
||||||
break
|
|
||||||
|
|
||||||
if not os.path.exists(temp_path):
|
|
||||||
raise HTTPException(status_code=404, detail="临时图片不存在或已过期")
|
|
||||||
|
|
||||||
# 创建收藏品图片目录
|
|
||||||
collection_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads", "collections")
|
|
||||||
os.makedirs(collection_dir, exist_ok=True)
|
|
||||||
|
|
||||||
# 生成新文件名
|
|
||||||
code = collection.f01_02_code or "0000"
|
code = collection.f01_02_code or "0000"
|
||||||
prefix = collection.f02_10_prefix_serial or ""
|
prefix = collection.f02_10_prefix_serial or ""
|
||||||
username = current_user.f01_01_name
|
username = current_user.f01_01_name
|
||||||
new_filename = f"{username}-{code}-{prefix}.jpg"
|
import time
|
||||||
new_path = os.path.join(collection_dir, new_filename)
|
final_filename = f"{username}-{code}-{prefix}-{int(time.time())}.jpg"
|
||||||
|
oss_key = f"collections/{final_filename}"
|
||||||
|
|
||||||
# 如果文件已存在,添加随机后缀
|
# 尝试从OSS获取临时图片 - 尝试多种扩展名
|
||||||
if os.path.exists(new_path):
|
temp_extensions = ['jpg', 'jpeg', 'png', 'gif']
|
||||||
name, ext = os.path.splitext(new_filename)
|
temp_content = None
|
||||||
new_filename = f"{name}-{str(uuid.uuid4())[:8]}{ext}"
|
found_ext = None
|
||||||
new_path = os.path.join(collection_dir, new_filename)
|
|
||||||
|
|
||||||
# 移动文件
|
for ext in temp_extensions:
|
||||||
|
try:
|
||||||
|
temp_oss_key = f"temp/{temp_id}.{ext}"
|
||||||
|
import oss2
|
||||||
|
auth = oss2.Auth(OSS_CONFIG["access_key_id"], OSS_CONFIG["access_key_secret"])
|
||||||
|
bucket = oss2.Bucket(auth, OSS_CONFIG["endpoint"], OSS_CONFIG["bucket_name"])
|
||||||
|
temp_content = bucket.get_object(temp_oss_key).read()
|
||||||
|
found_ext = ext
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if temp_content:
|
||||||
|
# 上传到正式目录
|
||||||
|
bucket.put_object(oss_key, temp_content)
|
||||||
|
|
||||||
|
# 删除临时图片
|
||||||
|
try:
|
||||||
|
bucket.delete_object(f"temp/{temp_id}.{found_ext}")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# OSS URL
|
||||||
|
image_path = f"{OSS_CONFIG['public_url']}/{oss_key}"
|
||||||
|
|
||||||
|
else:
|
||||||
|
# OSS失败,使用本地文件
|
||||||
|
temp_path = None
|
||||||
|
for ext in temp_extensions:
|
||||||
|
temp_path = os.path.join(UPLOAD_DIR, f"{temp_id}.{ext}")
|
||||||
|
if os.path.exists(temp_path):
|
||||||
|
break
|
||||||
|
|
||||||
|
if not temp_path or not os.path.exists(temp_path):
|
||||||
|
raise HTTPException(status_code=404, detail="临时图片不存在或已过期")
|
||||||
|
|
||||||
|
# 保存到本地
|
||||||
|
collection_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "uploads", "collections")
|
||||||
|
os.makedirs(collection_dir, exist_ok=True)
|
||||||
|
|
||||||
|
new_path = os.path.join(collection_dir, final_filename)
|
||||||
|
import shutil
|
||||||
shutil.move(temp_path, new_path)
|
shutil.move(temp_path, new_path)
|
||||||
|
image_path = f"uploads/collections/{final_filename}"
|
||||||
|
|
||||||
# 创建图片记录
|
# 创建图片记录
|
||||||
image_record = CollectionImage(
|
image_record = CollectionImage(
|
||||||
id=str(uuid.uuid4()),
|
id=str(uuid.uuid4()),
|
||||||
collection_id=collection.f99_90_id,
|
collection_id=collection.f99_90_id,
|
||||||
filename=new_filename,
|
filename=final_filename,
|
||||||
original_name=temp_filename,
|
original_name=temp_id,
|
||||||
path=f"uploads/collections/{new_filename}"
|
path=image_path
|
||||||
)
|
)
|
||||||
db.add(image_record)
|
db.add(image_record)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# Version Configuration for Zodiac Collection Management System
|
# Version Configuration for Zodiac Collection Management System
|
||||||
|
|
||||||
# 当前版本号 (语义化版本:主版本。次版本.修订版)
|
# 当前版本号 (语义化版本:主版本。次版本.修订版)
|
||||||
VERSION=1.1.5
|
VERSION=1.1.6
|
||||||
|
|
||||||
# 版本代号 (可选)
|
# 版本代号 (可选)
|
||||||
VERSION_CODENAME="新生"
|
VERSION_CODENAME="新生"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<title>甲辰收藏 v1.0.3-1773807001352</title>
|
<title>甲辰收藏 v1.1.5</title>
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/x-icon" href="/static/icons/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="/static/icons/favicon.ico" />
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ function getVersion() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const APP_VERSION = getVersion() + '-' + Date.now()
|
const APP_VERSION = getVersion()
|
||||||
console.log(`📦 构建版本:v${APP_VERSION}`)
|
console.log(`📦 构建版本:v${APP_VERSION}`)
|
||||||
|
|
||||||
// 构建时自动更新 index.html 的 title
|
// 构建时自动更新 index.html 的 title
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue