62 lines
2.3 KiB
Python
62 lines
2.3 KiB
Python
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
|
|
|
|
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 Exception as e:
|
|
return {
|
|
'code': 400,
|
|
'msg': f'上传失败:{str(e)}'
|
|
} |