from qiniu import Auth, put_file, put_data from django.conf import settings import time import os from PIL import Image from io import BytesIO import logging logger = logging.getLogger(__name__) class QiniuStorage: def __init__(self): self.q = Auth(settings.QINIU_ACCESS_KEY, settings.QINIU_SECRET_KEY) self.bucket_name = settings.QINIU_BUCKET_NAME self.domain = settings.QINIU_BUCKET_DOMAIN self.max_size = 5 * 1024 * 1024 # 5MB self.allowed_types = ['.jpg', '.jpeg', '.png', '.gif'] def compress_image(self, image_data): """无损压缩图片""" img = Image.open(BytesIO(image_data)) if img.mode in ('RGBA', 'P'): img = img.convert('RGB') output = BytesIO() # 保持原始尺寸,仅优化质量 img.save(output, format='JPEG', quality=85, optimize=True) return output.getvalue() def upload_data(self, file_data, file_path): """上传文件数据""" # 检查文件大小 if file_data.size > self.max_size: return {'code': 400, 'msg': f'文件大小不能超过{self.max_size/1024/1024}MB'} # 检查文件类型 ext = os.path.splitext(file_data.name)[1].lower() if ext not in self.allowed_types: return {'code': 400, 'msg': f'只支持{",".join(self.allowed_types)}格式的图片'} # 压缩图片 try: compressed_data = self.compress_image(file_data.read()) except Exception as e: return {'code': 400, 'msg': f'图片压缩失败:{str(e)}'} token = self.q.upload_token(self.bucket_name) timestamp = time.strftime('%Y-%m-%d/%Y%m%d%H%M%S', time.localtime()) key = f"{file_path}/{timestamp}_{str(int(time.time()*1000))[-3:]}{ext}" try: ret, info = put_data(token, key, compressed_data) if info.status_code == 200: base_url = f'http://{self.domain}/{key}' private_url = self.q.private_download_url(base_url, expires=3600*24*365) return { 'code': 200, 'url': private_url, 'msg': '上传成功' } # 在 except 中添加日志 except Exception as e: logger.error(f"七牛云上传失败: {str(e)}") return { 'code': 400, 'msg': f'上传失败:{str(e)}' }