fix cos
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
from typing import Optional
|
||||||
from backend.common.schema import SchemaBase
|
from backend.common.schema import SchemaBase
|
||||||
|
|
||||||
|
|
||||||
@@ -22,4 +22,4 @@ class QwenEmbedImageParams(QwenParamBase):
|
|||||||
class QwenRecognizeImageParams(QwenParamBase):
|
class QwenRecognizeImageParams(QwenParamBase):
|
||||||
""" Recognize image Params """
|
""" Recognize image Params """
|
||||||
type: str = Field(description='识别类型')
|
type: str = Field(description='识别类型')
|
||||||
exclude_words: list[str] = Field(description='exclude words')
|
exclude_words: Optional[list[str]] = Field(None, description='exclude words')
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
from pydantic import BaseModel, Field
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
class PurchaseRequest(BaseModel):
|
|
||||||
amount_cents: int = Field(..., ge=100, le=10000000, description="充值金额(分),1元=100分")
|
|
||||||
|
|
||||||
class SubscriptionRequest(BaseModel):
|
|
||||||
plan: str = Field(..., pattern=r'^(monthly|quarterly|half_yearly|yearly)$', description="订阅计划")
|
|
||||||
|
|
||||||
class RefundRequest(BaseModel):
|
|
||||||
order_id: int = Field(..., gt=0, description="订单ID")
|
|
||||||
reason: Optional[str] = Field(None, max_length=200, description="退款原因")
|
|
||||||
@@ -110,15 +110,7 @@ class FileService:
|
|||||||
if storage_type == "cos":
|
if storage_type == "cos":
|
||||||
cos_client = CosClient()
|
cos_client = CosClient()
|
||||||
key = cos_client.build_key(file_id)
|
key = cos_client.build_key(file_id)
|
||||||
avif_key = f"{file_id}_avif"
|
resp = cos_client.upload_object(key, content)
|
||||||
pic_ops = {
|
|
||||||
"is_pic_info": 1,
|
|
||||||
"rules": [{
|
|
||||||
"fileid": avif_key,
|
|
||||||
"rule": "imageMogr2/format/avif"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
resp = cos_client.upload_image(key, content, pic_ops)
|
|
||||||
|
|
||||||
data = None
|
data = None
|
||||||
if isinstance(resp, (list, tuple)) and len(resp) >= 2:
|
if isinstance(resp, (list, tuple)) and len(resp) >= 2:
|
||||||
@@ -132,7 +124,7 @@ class FileService:
|
|||||||
process_results = data.get("ProcessResults", {}) or {}
|
process_results = data.get("ProcessResults", {}) or {}
|
||||||
image_info = original_info.pop("ImageInfo", None)
|
image_info = original_info.pop("ImageInfo", None)
|
||||||
obj = process_results.get("Object", {}) or {}
|
obj = process_results.get("Object", {}) or {}
|
||||||
avif_key = avif_key
|
storage_path = obj.get("Key", key)
|
||||||
|
|
||||||
meta = FileMetadata(
|
meta = FileMetadata(
|
||||||
file_name=file.filename,
|
file_name=file.filename,
|
||||||
@@ -230,15 +222,7 @@ class FileService:
|
|||||||
else:
|
else:
|
||||||
cos_client = CosClient()
|
cos_client = CosClient()
|
||||||
key = cos_client.build_key(file_id)
|
key = cos_client.build_key(file_id)
|
||||||
avif_key = f"{key}_avif"
|
resp = cos_client.upload_object(key, content)
|
||||||
pic_ops = {
|
|
||||||
"is_pic_info": 1,
|
|
||||||
"rules": [{
|
|
||||||
"fileid": avif_key,
|
|
||||||
"rule": "imageMogr2/format/avif"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
resp = cos_client.upload_image(key, content, pic_ops)
|
|
||||||
|
|
||||||
data = None
|
data = None
|
||||||
if isinstance(resp, (list, tuple)) and len(resp) >= 2:
|
if isinstance(resp, (list, tuple)) and len(resp) >= 2:
|
||||||
@@ -252,10 +236,10 @@ class FileService:
|
|||||||
process_results = data.get("ProcessResults", {}) or {}
|
process_results = data.get("ProcessResults", {}) or {}
|
||||||
image_info = original_info.pop("ImageInfo", None)
|
image_info = original_info.pop("ImageInfo", None)
|
||||||
obj = process_results.get("Object", {}) or {}
|
obj = process_results.get("Object", {}) or {}
|
||||||
avif_key = obj.get("Key") or avif_key
|
storage_path = obj.get("Key") or key
|
||||||
|
|
||||||
update_params = UpdateFileParam(
|
update_params = UpdateFileParam(
|
||||||
storage_path=avif_key,
|
storage_path=storage_path,
|
||||||
metadata_info=FileMetadata(
|
metadata_info=FileMetadata(
|
||||||
file_name=file_name or "unnamed",
|
file_name=file_name or "unnamed",
|
||||||
content_type=content_type,
|
content_type=content_type,
|
||||||
@@ -269,7 +253,7 @@ class FileService:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
await file_dao.update(db, file_id, update_params)
|
await file_dao.update(db, file_id, update_params)
|
||||||
db_file.storage_path = avif_key
|
db_file.storage_path = storage_path
|
||||||
|
|
||||||
return FileUploadResponse(
|
return FileUploadResponse(
|
||||||
id=str(db_file.id),
|
id=str(db_file.id),
|
||||||
@@ -338,14 +322,17 @@ class FileService:
|
|||||||
db_file.file_data = content
|
db_file.file_data = content
|
||||||
await db.flush()
|
await db.flush()
|
||||||
else:
|
else:
|
||||||
|
cos_client = CosClient()
|
||||||
key = cos_client.build_key(file_id)
|
key = cos_client.build_key(file_id)
|
||||||
avif_key = f"{key}_avif"
|
avif_key = f"{file_id}_avif"
|
||||||
pic_ops = {
|
pic_ops = {
|
||||||
"is_pic_info": 1,
|
"is_pic_info": 1,
|
||||||
"rules": [{
|
"rules": [
|
||||||
|
{
|
||||||
"fileid": avif_key,
|
"fileid": avif_key,
|
||||||
"rule": "imageMogr2/format/avif"
|
"rule": "imageMogr2/format/avif"
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
resp = cos_client.upload_image(key, content, pic_ops)
|
resp = cos_client.upload_image(key, content, pic_ops)
|
||||||
|
|
||||||
@@ -361,10 +348,10 @@ class FileService:
|
|||||||
process_results = data.get("ProcessResults", {}) or {}
|
process_results = data.get("ProcessResults", {}) or {}
|
||||||
image_info = original_info.pop("ImageInfo", None)
|
image_info = original_info.pop("ImageInfo", None)
|
||||||
obj = process_results.get("Object", {}) or {}
|
obj = process_results.get("Object", {}) or {}
|
||||||
avif_key = obj.get("Key") or avif_key
|
storage_path = obj.get("Key") or avif_key
|
||||||
|
|
||||||
update_params = UpdateFileParam(
|
update_params = UpdateFileParam(
|
||||||
storage_path=avif_key,
|
storage_path=storage_path,
|
||||||
metadata_info=FileMetadata(
|
metadata_info=FileMetadata(
|
||||||
file_name=file.filename,
|
file_name=file.filename,
|
||||||
content_type=file.content_type,
|
content_type=file.content_type,
|
||||||
@@ -378,7 +365,7 @@ class FileService:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
await file_dao.update(db, file_id, update_params)
|
await file_dao.update(db, file_id, update_params)
|
||||||
db_file.storage_path = avif_key
|
db_file.storage_path = storage_path
|
||||||
|
|
||||||
return FileUploadResponse(
|
return FileUploadResponse(
|
||||||
id=str(db_file.id),
|
id=str(db_file.id),
|
||||||
@@ -413,6 +400,26 @@ class FileService:
|
|||||||
content = cos_client.download_object(key)
|
content = cos_client.download_object(key)
|
||||||
|
|
||||||
return content, db_file.file_name, db_file.content_type or "application/octet-stream"
|
return content, db_file.file_name, db_file.content_type or "application/octet-stream"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def download_image_file(file_id: int) -> tuple[bytes, str, str]:
|
||||||
|
"""下载文件"""
|
||||||
|
async with async_db_session() as db:
|
||||||
|
db_file = await file_dao.get(db, file_id)
|
||||||
|
if not db_file:
|
||||||
|
raise errors.NotFoundError(msg="文件不存在")
|
||||||
|
|
||||||
|
content = b""
|
||||||
|
|
||||||
|
if db_file.storage_type == "database":
|
||||||
|
# 从数据库获取文件数据
|
||||||
|
content = db_file.file_data or b""
|
||||||
|
else:
|
||||||
|
cos_client = CosClient()
|
||||||
|
key = cos_client.build_key(file_id)
|
||||||
|
content = cos_client.download_image(key)
|
||||||
|
|
||||||
|
return content, db_file.file_name, db_file.content_type or "application/octet-stream"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def delete_file(file_id: int) -> bool:
|
async def delete_file(file_id: int) -> bool:
|
||||||
|
|||||||
@@ -212,13 +212,13 @@ class ImageService:
|
|||||||
|
|
||||||
# 通过file_id读取文件内容
|
# 通过file_id读取文件内容
|
||||||
try:
|
try:
|
||||||
file_content, file_name, content_type = await file_service.download_file(file_id)
|
file_content, file_name, content_type = await file_service.download_image_file(file_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise errors.NotFoundError(msg=f"文件不存在或无法读取: {str(e)}")
|
raise errors.NotFoundError(msg=f"文件不存在或无法读取: {str(e)}")
|
||||||
|
|
||||||
# 提前提取图片格式
|
# 提前提取图片格式
|
||||||
image_format = image_service.detect_image_format(file_content)
|
# image_format = image_service.detect_image_format(file_content)
|
||||||
image_format_str = image_format.value
|
# image_format_str = image_format.value
|
||||||
|
|
||||||
base64_image = base64.b64encode(file_content).decode('utf-8')
|
base64_image = base64.b64encode(file_content).decode('utf-8')
|
||||||
|
|
||||||
@@ -465,22 +465,13 @@ class ImageService:
|
|||||||
)
|
)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
return
|
return
|
||||||
|
|
||||||
# 获取exclude_words
|
|
||||||
exclude_words = []
|
|
||||||
if image.details and "recognition_result" in image.details:
|
|
||||||
recognition_result = image.details["recognition_result"]
|
|
||||||
exclude_words.extend([
|
|
||||||
word for section in recognition_result.values()
|
|
||||||
for word in section.get('ref_word', [])
|
|
||||||
if isinstance(section.get('ref_word'), list)
|
|
||||||
])
|
|
||||||
|
|
||||||
# 提交当前事务,释放锁
|
# 提交当前事务,释放锁
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
# 下载文件(在数据库事务外执行)
|
# 下载文件(在数据库事务外执行)
|
||||||
file_content, file_name, content_type = await file_service.download_file(task.file_id)
|
file_content, file_name, content_type = await file_service.download_image_file(task.file_id)
|
||||||
|
print(len(file_content))
|
||||||
image_format = image_service.detect_image_format(file_content)
|
image_format = image_service.detect_image_format(file_content)
|
||||||
image_format_str = image_format.value
|
image_format_str = image_format.value
|
||||||
base64_image = base64.b64encode(file_content).decode('utf-8')
|
base64_image = base64.b64encode(file_content).decode('utf-8')
|
||||||
@@ -494,8 +485,7 @@ class ImageService:
|
|||||||
format=image_format_str,
|
format=image_format_str,
|
||||||
data=base64_image,
|
data=base64_image,
|
||||||
type=task.type,
|
type=task.type,
|
||||||
dict_level=task.dict_level,
|
dict_level=task.dict_level
|
||||||
exclude_words=list(set(exclude_words)) # 去重
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Make the external API call without holding a database connection
|
# Make the external API call without holding a database connection
|
||||||
|
|||||||
@@ -57,12 +57,20 @@ class CosClient:
|
|||||||
|
|
||||||
def download_object(self, key: str) -> bytes:
|
def download_object(self, key: str) -> bytes:
|
||||||
try:
|
try:
|
||||||
resp = self.client.get_object(Bucket=self.bucket, Key=key)
|
resp = self.client.get_object(Bucket=self.bucket, Key=key, )
|
||||||
return resp['Body'].get_raw_stream().read()
|
return resp['Body'].get_raw_stream().read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"cos download_object failed: {e}")
|
logger.error(f"cos download_object failed: {e}")
|
||||||
raise errors.ServerError(msg="COS download failed")
|
raise errors.ServerError(msg="COS download failed")
|
||||||
|
|
||||||
|
def download_image(self, key: str) -> bytes:
|
||||||
|
try:
|
||||||
|
resp = self.client.get_object(Bucket=self.bucket, Key=key)
|
||||||
|
return resp['Body'].get_raw_stream().read()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"cos download_image failed: {e}")
|
||||||
|
raise errors.ServerError(msg="COS download failed")
|
||||||
|
|
||||||
def copy_object(self, src_file_id: str, dest_file_id: str) -> dict:
|
def copy_object(self, src_file_id: str, dest_file_id: str) -> dict:
|
||||||
try:
|
try:
|
||||||
src_key = self.build_key(src_file_id)
|
src_key = self.build_key(src_file_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user