147 lines
5.8 KiB
Python
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() |