vault backup: 2025-12-26 02:09:22
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
All checks were successful
Deploy Quartz site to GitHub Pages / build (push) Successful in 2m29s
This commit is contained in:
101
stroma/file/views/upload_files_api_view.py
Normal file
101
stroma/file/views/upload_files_api_view.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import os
|
||||
import mimetypes
|
||||
from pathlib import Path
|
||||
|
||||
from django.http import JsonResponse
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from file.models import File
|
||||
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
def upload_files_api(request):
|
||||
"""Handle file/folder uploads and create File model instances"""
|
||||
|
||||
uploaded_files = request.FILES.getlist('files')
|
||||
|
||||
if not uploaded_files:
|
||||
return JsonResponse({'error': 'No files uploaded'}, status=400)
|
||||
|
||||
created_files = []
|
||||
folder_cache = {} # Cache for created folder objects
|
||||
|
||||
for idx, uploaded_file in enumerate(uploaded_files):
|
||||
# Get the relative path if it exists (from webkitRelativePath)
|
||||
relative_path = request.POST.get(f'path_{idx}', '')
|
||||
|
||||
if relative_path:
|
||||
# This is from a folder upload
|
||||
path_obj = Path(relative_path)
|
||||
parts = path_obj.parts
|
||||
|
||||
# Create parent folders if needed
|
||||
parent = None
|
||||
for i, part in enumerate(parts[:-1]): # Exclude the file itself
|
||||
folder_path = os.path.join(*parts[:i+1])
|
||||
|
||||
if folder_path not in folder_cache:
|
||||
# Create or get folder
|
||||
folder, created = File.objects.get_or_create(
|
||||
user=request.quiz_user,
|
||||
path=folder_path,
|
||||
defaults={
|
||||
'name': part,
|
||||
'mime_type': 'application/x-folder',
|
||||
'parent': parent
|
||||
}
|
||||
)
|
||||
folder_cache[folder_path] = folder
|
||||
|
||||
parent = folder_cache[folder_path]
|
||||
|
||||
file_path = relative_path
|
||||
file_name = parts[-1]
|
||||
else:
|
||||
# Single file upload
|
||||
file_path = uploaded_file.name
|
||||
file_name = uploaded_file.name
|
||||
parent = None
|
||||
|
||||
# Determine MIME type
|
||||
mime_type, _ = mimetypes.guess_type(file_name)
|
||||
if not mime_type:
|
||||
mime_type = 'application/octet-stream'
|
||||
|
||||
# Read file content (for text files, store in text field)
|
||||
text_content = ''
|
||||
if mime_type.startswith('text/'):
|
||||
try:
|
||||
content_bytes = uploaded_file.read()
|
||||
text_content = content_bytes.decode('utf-8')
|
||||
uploaded_file.seek(0) # Reset for saving to disk
|
||||
except (UnicodeDecodeError, AttributeError):
|
||||
uploaded_file.seek(0)
|
||||
|
||||
# Generate unique filename with 8-digit hash
|
||||
import hashlib
|
||||
file_hash = hashlib.md5(f"{file_path}{uploaded_file.name}".encode()).hexdigest()[:8]
|
||||
name_parts = os.path.splitext(file_name)
|
||||
unique_filename = f"{name_parts[0]}_{file_hash}{name_parts[1]}"
|
||||
|
||||
# Create File instance
|
||||
file_obj = File.objects.create(
|
||||
user=request.quiz_user,
|
||||
name=file_name,
|
||||
path=file_path,
|
||||
mime_type=mime_type,
|
||||
parent=parent,
|
||||
text=text_content
|
||||
)
|
||||
|
||||
# Save the uploaded file to disk (not for folders)
|
||||
if mime_type != 'application/x-folder':
|
||||
file_obj.file_content.save(unique_filename, uploaded_file, save=True)
|
||||
|
||||
created_files.append(file_obj)
|
||||
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'count': len(created_files),
|
||||
'files': [{'name': f.name, 'path': f.path} for f in created_files]
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user