File size: 3,019 Bytes
1fce3ef
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""
File handling utilities
Upload, download, and manage files
"""

import os
import uuid
from typing import Optional
from pathlib import Path
from fastapi import UploadFile, HTTPException

from app.core.constants import (
    MAX_UPLOAD_SIZE,
    ALLOWED_DOCUMENT_EXTENSIONS,
    ALLOWED_IMAGE_EXTENSIONS,
    DOCUMENTS_DIR,
    IMAGES_DIR
)


def validate_file_size(file: UploadFile, max_size: int = MAX_UPLOAD_SIZE) -> bool:
    """
    Validate file size
    
    Args:
        file: Uploaded file
        max_size: Maximum allowed size in bytes
        
    Returns:
        True if valid
        
    Raises:
        HTTPException: If file is too large
    """
    file.file.seek(0, 2)  # Seek to end
    file_size = file.file.tell()
    file.file.seek(0)  # Reset
    
    if file_size > max_size:
        raise HTTPException(
            status_code=413,
            detail=f"File too large. Maximum size: {max_size / 1024 / 1024:.1f}MB"
        )
    
    return True


def validate_file_extension(filename: str, allowed_extensions: set) -> bool:
    """
    Validate file extension
    
    Args:
        filename: File name
        allowed_extensions: Set of allowed extensions
        
    Returns:
        True if valid
        
    Raises:
        HTTPException: If extension not allowed
    """
    ext = Path(filename).suffix.lower()
    
    if ext not in allowed_extensions:
        raise HTTPException(
            status_code=400,
            detail=f"File type not allowed. Allowed: {', '.join(allowed_extensions)}"
        )
    
    return True


def generate_unique_filename(original_filename: str) -> str:
    """
    Generate unique filename
    
    Args:
        original_filename: Original file name
        
    Returns:
        Unique filename
    """
    ext = Path(original_filename).suffix
    unique_name = f"{uuid.uuid4()}{ext}"
    return unique_name


async def save_upload_file(
    file: UploadFile,
    destination_dir: str,
    allowed_extensions: set = ALLOWED_DOCUMENT_EXTENSIONS
) -> str:
    """
    Save uploaded file
    
    Args:
        file: Uploaded file
        destination_dir: Directory to save file
        allowed_extensions: Allowed file extensions
        
    Returns:
        Saved file path
    """
    # Validate
    validate_file_size(file)
    validate_file_extension(file.filename, allowed_extensions)
    
    # Create directory if not exists
    os.makedirs(destination_dir, exist_ok=True)
    
    # Generate unique filename
    filename = generate_unique_filename(file.filename)
    file_path = os.path.join(destination_dir, filename)
    
    # Save file
    with open(file_path, "wb") as f:
        content = await file.read()
        f.write(content)
    
    return file_path


def delete_file(file_path: str) -> bool:
    """
    Delete file
    
    Args:
        file_path: Path to file
        
    Returns:
        True if deleted
    """
    if os.path.exists(file_path):
        os.remove(file_path)
        return True
    return False