# File Management Service

**Author**: Josh S. Sakweli, Backend Lead Team  
**Last Updated**: 2025-09-23  
**Version**: v1.0

**Short Description**: The File Management Service handles file uploads, downloads, and management for the NextGate social commerce platform. This service provides secure file storage with support for multiple file types, automatic metadata extraction, and organized directory structures for profiles, categories, and shops.

**Hints**: 
- Maximum file size: 25MB per file
- Supported file types: Images (JPEG, PNG, GIF, WebP, BMP, SVG), Videos (MP4, AVI, MOV, WebM, MKV), Documents (PDF, DOC, DOCX, TXT, XLS), Audio (MP3, WAV, OGG, AAC)
- All uploaded files are publicly accessible via direct URLs
- Files are automatically organized by directory type (profile, categories, shops)
- Image dimensions and metadata are automatically extracted
- Unique filenames are generated to prevent conflicts
- MD5 checksums are calculated for file integrity verification

---

## Endpoints

## 1. Upload Multiple Files
**Purpose**: Upload multiple files to a specified directory with comprehensive metadata extraction

**Endpoint**: <span style="background-color: #fd7e14; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span> `https://apinexgate.glueauth.com/api/v1/files/upload`

**Access Level**: 🔒 Protected (Requires JWT Bearer token)

**Authentication**: Bearer Token (JWT access token required)

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer {access_token} |
| Content-Type | string | Yes | Must be "multipart/form-data" |

**Request Form Data Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| files | file[] | Yes | Array of files to upload | Max 25MB per file, supported file types only |
| directory | string | Yes | Target directory for files | enum: PROFILE, CATEGORIES, SHOPS |

**Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Files uploaded successfully",
  "action_time": "2025-09-23T10:30:00",
  "data": {
    "uploadedFiles": [
      {
        "fileName": "123e4567-e89b-12d3-a456-426614174000.jpg",
        "originalFileName": "product-image.jpg",
        "objectKey": "profile/123e4567-e89b-12d3-a456-426614174000.jpg",
        "directory": "PROFILE",
        "contentType": "image/jpeg",
        "fileSize": 2048576,
        "fileSizeFormatted": "2.0 MB",
        "permanentUrl": "https://files.nextgate.com/bucket-uuid/profile/123e4567-e89b-12d3-a456-426614174000.jpg",
        "thumbnailUrl": "https://files.nextgate.com/bucket-uuid/profile/123e4567-e89b-12d3-a456-426614174000.jpg",
        "fileExtension": ".jpg",
        "fileType": "IMAGE",
        "isImage": true,
        "isVideo": false,
        "isDocument": false,
        "isAudio": false,
        "width": 1920,
        "height": 1080,
        "dimensions": "1920x1080",
        "checksum": "d41d8cd98f00b204e9800998ecf8427e",
        "uploadedAt": "2025-09-23T10:30:00",
        "uploadedBy": "123e4567-e89b-12d3-a456-426614174000",
        "isPublic": true
      }
    ],
    "totalFiles": 3,
    "successfulUploads": 2,
    "failedUploads": 1,
    "totalSize": 5242880,
    "totalSizeFormatted": "5.0 MB",
    "uploadedAt": "2025-09-23T10:30:00",
    "message": "2 files uploaded successfully, 1 failed",
    "errors": [
      "Failed to upload large-file.mp4: File size exceeds maximum limit of 25MB"
    ]
  }
}
```

**Response Fields**:
| Field | Description |
|-------|-------------|
| success | Boolean indicating operation success |
| httpStatus | HTTP status code as string |
| message | Overall operation success message |
| action_time | ISO 8601 timestamp of response generation |
| data.uploadedFiles | Array of successfully uploaded file details |
| data.uploadedFiles[].fileName | System-generated unique filename with UUID |
| data.uploadedFiles[].originalFileName | Original filename provided by user |
| data.uploadedFiles[].objectKey | Full object path in storage system |
| data.uploadedFiles[].directory | Directory where file was stored |
| data.uploadedFiles[].contentType | MIME type of the uploaded file |
| data.uploadedFiles[].fileSize | File size in bytes |
| data.uploadedFiles[].fileSizeFormatted | Human-readable file size (e.g., "2.0 MB") |
| data.uploadedFiles[].permanentUrl | Direct public URL to access the file |
| data.uploadedFiles[].thumbnailUrl | Thumbnail URL (same as permanentUrl for images) |
| data.uploadedFiles[].fileExtension | File extension including dot (e.g., ".jpg") |
| data.uploadedFiles[].fileType | File category (IMAGE, VIDEO, DOCUMENT, AUDIO, OTHER) |
| data.uploadedFiles[].isImage | Boolean indicating if file is an image |
| data.uploadedFiles[].isVideo | Boolean indicating if file is a video |
| data.uploadedFiles[].isDocument | Boolean indicating if file is a document |
| data.uploadedFiles[].isAudio | Boolean indicating if file is audio |
| data.uploadedFiles[].width | Image width in pixels (images only) |
| data.uploadedFiles[].height | Image height in pixels (images only) |
| data.uploadedFiles[].dimensions | Image dimensions as "WxH" format |
| data.uploadedFiles[].checksum | MD5 hash of file content for integrity verification |
| data.uploadedFiles[].uploadedAt | Upload timestamp |
| data.uploadedFiles[].uploadedBy | Account ID of uploader |
| data.uploadedFiles[].isPublic | Boolean indicating public accessibility (always true) |
| data.totalFiles | Total number of files in upload request |
| data.successfulUploads | Number of successfully uploaded files |
| data.failedUploads | Number of failed uploads |
| data.totalSize | Total size of all uploaded files in bytes |
| data.totalSizeFormatted | Human-readable total size |
| data.uploadedAt | Overall upload completion timestamp |
| data.message | Summary message of upload results |
| data.errors | Array of error messages for failed uploads (null if no errors) |

**Error Responses**:
- `400 Bad Request`: Invalid file format, missing parameters, or validation errors
- `401 Unauthorized`: Missing or invalid JWT token
- `413 Payload Too Large`: File size exceeds 25MB limit
- `422 Unprocessable Entity`: Unsupported file type or directory
- `500 Internal Server Error`: Storage system errors

---

## 2. Upload Single File
**Purpose**: Upload a single file to a specified directory with detailed metadata extraction

**Endpoint**: <span style="background-color: #fd7e14; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span> `https://apinexgate.glueauth.com/api/v1/files/upload-single`

**Access Level**: 🔒 Protected (Requires JWT Bearer token)

**Authentication**: Bearer Token (JWT access token required)

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer {access_token} |
| Content-Type | string | Yes | Must be "multipart/form-data" |

**Request Form Data Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| file | file | Yes | Single file to upload | Max 25MB, supported file types only |
| directory | string | Yes | Target directory for the file | enum: PROFILE, CATEGORIES, SHOPS |

**Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "File uploaded successfully",
  "action_time": "2025-09-23T10:30:00",
  "data": {
    "fileName": "123e4567-e89b-12d3-a456-426614174000.pdf",
    "originalFileName": "product-catalog.pdf",
    "objectKey": "categories/123e4567-e89b-12d3-a456-426614174000.pdf",
    "directory": "CATEGORIES",
    "contentType": "application/pdf",
    "fileSize": 1048576,
    "fileSizeFormatted": "1.0 MB",
    "permanentUrl": "https://files.nextgate.com/bucket-uuid/categories/123e4567-e89b-12d3-a456-426614174000.pdf",
    "thumbnailUrl": null,
    "fileExtension": ".pdf",
    "fileType": "DOCUMENT",
    "isImage": false,
    "isVideo": false,
    "isDocument": true,
    "isAudio": false,
    "width": null,
    "height": null,
    "dimensions": null,
    "checksum": "5d41402abc4b2a76b9719d911017c592",
    "uploadedAt": "2025-09-23T10:30:00",
    "uploadedBy": "123e4567-e89b-12d3-a456-426614174000",
    "isPublic": true
  }
}
```

**Response Fields**:
| Field | Description |
|-------|-------------|
| success | Boolean indicating operation success |
| httpStatus | HTTP status code as string |
| message | Success message |
| action_time | ISO 8601 timestamp of response generation |
| data | Single FileResponse object with complete file metadata (same structure as uploadedFiles[] items above) |

**Error Responses**:
- `400 Bad Request`: Invalid file, missing parameters, or validation errors
- `401 Unauthorized`: Missing or invalid JWT token
- `413 Payload Too Large`: File size exceeds 25MB limit
- `422 Unprocessable Entity`: Unsupported file type or directory
- `500 Internal Server Error`: Storage system errors

---

## 3. Get User Files by Directory
**Purpose**: Retrieve all files uploaded by the authenticated user in a specific directory

**Endpoint**: <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span> `https://apinexgate.glueauth.com/api/v1/files/directory/{directory}`

**Access Level**: 🔒 Protected (Requires JWT Bearer token)

**Authentication**: Bearer Token (JWT access token required)

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer {access_token} |
| Content-Type | string | Yes | Must be "application/json" |

**Path Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| directory | string | Yes | Directory to list files from | enum: PROFILE, CATEGORIES, SHOPS |

**Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Files retrieved successfully",
  "action_time": "2025-09-23T10:30:00",
  "data": [
    {
      "fileName": "123e4567-e89b-12d3-a456-426614174000.jpg",
      "originalFileName": "profile-picture.jpg",
      "objectKey": "profile/123e4567-e89b-12d3-a456-426614174000.jpg",
      "directory": "PROFILE",
      "contentType": "image/jpeg",
      "fileSize": 2048576,
      "fileSizeFormatted": "2.0 MB",
      "permanentUrl": "https://files.nextgate.com/bucket-uuid/profile/123e4567-e89b-12d3-a456-426614174000.jpg",
      "thumbnailUrl": "https://files.nextgate.com/bucket-uuid/profile/123e4567-e89b-12d3-a456-426614174000.jpg",
      "fileExtension": ".jpg",
      "fileType": "IMAGE",
      "isImage": true,
      "isVideo": false,
      "isDocument": false,
      "isAudio": false,
      "width": 1920,
      "height": 1080,
      "dimensions": "1920x1080",
      "uploadedBy": "123e4567-e89b-12d3-a456-426614174000",
      "isPublic": true
    },
    {
      "fileName": "456e7890-e89b-12d3-a456-426614174111.png",
      "originalFileName": "banner-image.png",
      "objectKey": "profile/456e7890-e89b-12d3-a456-426614174111.png",
      "directory": "PROFILE",
      "contentType": "image/png",
      "fileSize": 1524288,
      "fileSizeFormatted": "1.5 MB",
      "permanentUrl": "https://files.nextgate.com/bucket-uuid/profile/456e7890-e89b-12d3-a456-426614174111.png",
      "thumbnailUrl": "https://files.nextgate.com/bucket-uuid/profile/456e7890-e89b-12d3-a456-426614174111.png",
      "fileExtension": ".png",
      "fileType": "IMAGE",
      "isImage": true,
      "isVideo": false,
      "isDocument": false,
      "isAudio": false,
      "width": 1600,
      "height": 900,
      "dimensions": "1600x900",
      "uploadedBy": "123e4567-e89b-12d3-a456-426614174000",
      "isPublic": true
    }
  ]
}
```

**Response Fields**:
| Field | Description |
|-------|-------------|
| success | Boolean indicating operation success |
| httpStatus | HTTP status code as string |
| message | Success message |
| action_time | ISO 8601 timestamp of response generation |
| data | Array of FileResponse objects for all files in the specified directory |

**Error Responses**:
- `400 Bad Request`: Invalid directory parameter
- `401 Unauthorized`: Missing or invalid JWT token
- `404 Not Found`: Directory not found or user not found
- `500 Internal Server Error`: Storage system errors

---

## 4. Delete File
**Purpose**: Delete a specific file uploaded by the authenticated user

**Endpoint**: <span style="background-color: #dc3545; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">DELETE</span> `https://apinexgate.glueauth.com/api/v1/files/{objectKey}`

**Access Level**: 🔒 Protected (Requires JWT Bearer token)

**Authentication**: Bearer Token (JWT access token required)

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | Bearer {access_token} |
| Content-Type | string | Yes | Must be "application/json" |

**Path Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| objectKey | string | Yes | Full object key/path of the file to delete | Must be a valid object key from user's files |

**Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "File deleted successfully",
  "action_time": "2025-09-23T10:30:00",
  "data": null
}
```

**Response Fields**:
| Field | Description |
|-------|-------------|
| success | Boolean indicating operation success |
| httpStatus | HTTP status code as string |
| message | Success message confirming deletion |
| action_time | ISO 8601 timestamp of response generation |
| data | Always null for delete operations |

**Error Responses**:
- `400 Bad Request`: Invalid object key format
- `401 Unauthorized`: Missing or invalid JWT token
- `404 Not Found`: File not found or user not found
- `403 Forbidden`: Attempting to delete file not owned by user
- `500 Internal Server Error`: Storage system errors

---

## Quick Reference Guide

### File Directory Types
- **PROFILE**: User profile images, avatars, and personal media
- **CATEGORIES**: Category images, banners, and related media
- **SHOPS**: Shop-related images, logos, and promotional materials

### Supported File Types
- **Images**: JPEG, JPG, PNG, GIF, WebP, BMP, SVG
- **Videos**: MP4, AVI, MOV, WMV, FLV, WebM, MKV
- **Documents**: PDF, DOC, DOCX, TXT, XLS
- **Audio**: MP3, WAV, OGG, AAC

### File Size and Limits
- **Maximum file size**: 25MB per file
- **File naming**: Original names preserved, unique UUIDs generated for storage
- **Public access**: All uploaded files are publicly accessible via direct URLs
- **Checksums**: MD5 hashes calculated for file integrity verification

### Common HTTP Status Codes
- `200 OK`: Successful GET/DELETE request
- `201 Created`: Successful POST request (file upload)
- `400 Bad Request`: Invalid request data or file validation errors
- `401 Unauthorized`: Authentication required/failed
- `403 Forbidden`: Insufficient permissions
- `404 Not Found`: Resource not found
- `413 Payload Too Large`: File size exceeds limit
- `422 Unprocessable Entity`: Validation errors
- `500 Internal Server Error`: Server error

### Authentication Types
- **Bearer Token**: Include `Authorization: Bearer your_access_token` in headers
- **Form Data**: Use `multipart/form-data` for file uploads
- **JSON**: Use `application/json` for other requests

### Data Format Standards
- **Dates**: Use ISO 8601 format (2025-09-23T10:30:00Z)
- **File sizes**: Provided in bytes and human-readable format
- **UUIDs**: Standard UUID format for all identifiers
- **URLs**: Full HTTPS URLs for file access