c1aac7ecac
Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
3.0 KiB
Python
97 lines
3.0 KiB
Python
import os
|
|
import uuid
|
|
from datetime import datetime, timezone
|
|
|
|
from werkzeug.utils import secure_filename
|
|
|
|
from app import db
|
|
from app.models import Photo
|
|
from app.quota_utils import check_upload_quota
|
|
from app.settings_service import get_settings
|
|
from app.storage_service import save_photo_file
|
|
|
|
|
|
def allowed_file(filename, allowed_extensions):
|
|
return "." in filename and filename.rsplit(".", 1)[1].lower() in allowed_extensions
|
|
|
|
|
|
def collect_upload_files(request_files):
|
|
files = request_files.getlist("photos")
|
|
if not files or all(f.filename == "" for f in files):
|
|
single = request_files.get("photo")
|
|
if single and single.filename:
|
|
files = [single]
|
|
return [f for f in files if f and f.filename]
|
|
|
|
|
|
def process_uploads(request_files, user, folder, allowed_extensions):
|
|
settings = get_settings()
|
|
max_bulk = settings.max_bulk_upload or 100
|
|
files = collect_upload_files(request_files)
|
|
|
|
if not files:
|
|
return {"uploaded": 0, "errors": ["Файлы не выбраны"], "photos": []}
|
|
|
|
if len(files) > max_bulk:
|
|
return {
|
|
"uploaded": 0,
|
|
"errors": [f"Максимум {max_bulk} файлов за раз"],
|
|
"photos": [],
|
|
}
|
|
|
|
total_size = 0
|
|
valid_files = []
|
|
errors = []
|
|
|
|
for file in files:
|
|
if not allowed_file(file.filename, allowed_extensions):
|
|
errors.append(f"{file.filename}: недопустимый формат")
|
|
continue
|
|
file.seek(0, os.SEEK_END)
|
|
size = file.tell()
|
|
file.seek(0)
|
|
total_size += size
|
|
valid_files.append((file, size))
|
|
|
|
if not valid_files:
|
|
return {"uploaded": 0, "errors": errors, "photos": []}
|
|
|
|
ok, quota_msg = check_upload_quota(user, total_size)
|
|
if not ok:
|
|
return {"uploaded": 0, "errors": [quota_msg], "photos": []}
|
|
|
|
uploaded_photos = []
|
|
for file, _size in valid_files:
|
|
ext = file.filename.rsplit(".", 1)[1].lower()
|
|
stored_name = f"{uuid.uuid4().hex}.{ext}"
|
|
safe_original = secure_filename(file.filename) or f"photo.{ext}"
|
|
|
|
try:
|
|
_path, file_size, storage_backend, sync_errors = save_photo_file(file, stored_name)
|
|
for sync_err in sync_errors:
|
|
errors.append(f"{safe_original}: {sync_err}")
|
|
|
|
photo = Photo(
|
|
filename=stored_name,
|
|
original_name=safe_original,
|
|
file_size=file_size,
|
|
mime_type=file.content_type or f"image/{ext}",
|
|
user_id=user.id,
|
|
folder_id=folder.id if folder else None,
|
|
storage_backend=storage_backend,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|
|
db.session.add(photo)
|
|
uploaded_photos.append(photo)
|
|
except Exception as exc:
|
|
errors.append(f"{safe_original}: {exc}")
|
|
|
|
if uploaded_photos:
|
|
db.session.commit()
|
|
|
|
return {
|
|
"uploaded": len(uploaded_photos),
|
|
"errors": errors,
|
|
"photos": uploaded_photos,
|
|
}
|