imetting_backend/app/services/qiniu_service.py

147 lines
5.8 KiB
Python

from qiniu import Auth, put_file_v2, etag, BucketManager
import qiniu.config
import os
import uuid
from typing import Optional, Tuple
from app.core.config import QINIU_ACCESS_KEY, QINIU_SECRET_KEY, QINIU_BUCKET, QINIU_DOMAIN
class QiniuService:
def __init__(self):
self.access_key = QINIU_ACCESS_KEY
self.secret_key = QINIU_SECRET_KEY
self.bucket_name = QINIU_BUCKET
self.domain = QINIU_DOMAIN
if not self.access_key or not self.secret_key:
print("ERROR: 七牛云Access Key或Secret Key为空!")
if not self.bucket_name:
print("ERROR: 七牛云Bucket名称为空!")
if not self.domain:
print("ERROR: 七牛云Domain为空!")
self.q = Auth(self.access_key, self.secret_key)
def upload_audio_file(self, file_path: str, meeting_id: int, original_filename: str) -> Tuple[bool, str, Optional[str]]:
"""
Upload audio file to Qiniu cloud storage
Args:
file_path: Local file path
meeting_id: Meeting ID for directory structure
original_filename: Original filename
Returns:
Tuple of (success: bool, url: str, error_message: Optional[str])
"""
try:
# Validate file exists
if not os.path.exists(file_path):
return False, "", f"File not found: {file_path}"
file_extension = os.path.splitext(original_filename)[1]
unique_filename = f"{uuid.uuid4()}{file_extension}"
key = f"record/{meeting_id}/{unique_filename}"
# Generate upload token
token = self.q.upload_token(self.bucket_name, key, 3600)
print(f"DEBUG: 生成音频上传token成功, key: {key}")
print(f"DEBUG: token前50位: {token[:50] if token else 'None'}")
# Upload file with retry mechanism
ret, info = put_file_v2(token, key, file_path)
print(f"DEBUG: Qiniu upload response - ret: {ret}, info: {info}")
print(f"DEBUG: Qiniu upload info details - status_code: {info.status_code}, text_body: {info.text_body}")
# Check if upload was successful
# For put_file_v2, we need to check the info.status_code
if info.status_code == 200 and ret and 'key' in ret and ret['key'] == key:
url = f"http://{self.domain}/{key}"
return True, url, None
else:
# Extract error information properly
error_msg = f"Upload failed: status_code={info.status_code}"
if hasattr(info, 'text_body') and info.text_body:
error_msg += f", response={info.text_body}"
return False, "", error_msg
except Exception as e:
import traceback
traceback.print_exc()
return False, "", f"Upload error: {str(e)}"
def upload_markdown_image(self, file_path: str, meeting_id: int, original_filename: str) -> Tuple[bool, str, Optional[str]]:
"""
Upload markdown image to Qiniu cloud storage
Args:
file_path: Local file path
meeting_id: Meeting ID for directory structure
original_filename: Original filename
Returns:
Tuple of (success: bool, url: str, error_message: Optional[str])
"""
try:
# Validate file exists
if not os.path.exists(file_path):
return False, "", f"File not found: {file_path}"
file_extension = os.path.splitext(original_filename)[1]
unique_filename = f"{uuid.uuid4()}{file_extension}"
key = f"markdown/{meeting_id}/{unique_filename}"
# Generate upload token
token = self.q.upload_token(self.bucket_name, key, 3600)
# Upload file with retry mechanism
ret, info = put_file_v2(token, key, file_path)
print(f"DEBUG: Qiniu image upload response - ret: {ret}, info: {info}")
print(f"DEBUG: Qiniu image upload info details - status_code: {info.status_code}, text_body: {info.text_body}")
# Check if upload was successful
# For put_file_v2, we need to check the info.status_code
if info.status_code == 200 and ret and 'key' in ret and ret['key'] == key:
url = f"http://{self.domain}/{key}"
return True, url, None
else:
# Extract error information properly
error_msg = f"Upload failed: status_code={info.status_code}"
if hasattr(info, 'text_body') and info.text_body:
error_msg += f", response={info.text_body}"
return False, "", error_msg
except Exception as e:
import traceback
traceback.print_exc()
return False, "", f"Upload error: {str(e)}"
def delete_file(self, key: str) -> Tuple[bool, Optional[str]]:
"""
Delete file from Qiniu cloud storage
Args:
key: File key in Qiniu storage
Returns:
Tuple of (success: bool, error_message: Optional[str])
"""
try:
from qiniu import BucketManager
bucket = BucketManager(self.q)
ret, info = bucket.delete(self.bucket_name, key)
if ret is None:
return True, None
else:
return False, f"Delete failed: {info}"
except Exception as e:
return False, f"Delete error: {str(e)}"
# Global instance
qiniu_service = QiniuService()