Files
orion/docs/operations/image-storage.md
Samir Boulahtit e9253fbd84 refactor: rename Wizamart to Orion across entire codebase
Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart
with Orion/orion/ORION across 184 files. This includes database
identifiers, email addresses, domain references, R2 bucket names,
DNS prefixes, encryption salt, Celery app name, config defaults,
Docker configs, CI configs, documentation, seed data, and templates.

Renames homepage-wizamart.html template to homepage-orion.html.
Fixes duplicate file_pattern key in api.yaml architecture rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:46:56 +01:00

247 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Image Storage System
Documentation for the platform's image storage and management system.
## Overview
The Orion platform uses a self-hosted image storage system with:
- **Sharded directory structure** for filesystem performance
- **Automatic WebP conversion** for optimization
- **Multiple size variants** for different use cases
- **CDN-ready architecture** for scaling
## Storage Architecture
### Directory Structure
Images are stored in a sharded directory structure to prevent filesystem performance degradation:
```
/static/uploads/
└── products/
├── 00/ # First 2 chars of hash
│ ├── 1a/ # Next 2 chars
│ │ ├── 001a2b3c_original.webp
│ │ ├── 001a2b3c_800.webp
│ │ └── 001a2b3c_200.webp
│ └── 2b/
│ └── ...
├── 01/
│ └── ...
└── ff/
└── ...
```
### Hash Generation
The file hash is generated from:
```python
hash = md5(f"{store_id}:{product_id}:{timestamp}:{original_filename}")[:8]
```
This ensures:
- Unique file paths
- Even distribution across directories
- Predictable file locations
## Image Variants
Each uploaded image generates multiple variants:
| Variant | Max Dimensions | Format | Use Case |
|---------|---------------|--------|----------|
| `original` | As uploaded (max 2000px) | WebP | Detail view, zoom |
| `800` | 800×800 | WebP | Product cards |
| `200` | 200×200 | WebP | Thumbnails, grids |
### Size Estimates
| Original Size | After Processing | Storage per Image |
|---------------|------------------|-------------------|
| 2MB JPEG | ~200KB (original) + 80KB (800) + 15KB (200) | ~295KB |
| 500KB JPEG | ~150KB (original) + 60KB (800) + 12KB (200) | ~222KB |
| 100KB JPEG | ~80KB (original) + 40KB (800) + 10KB (200) | ~130KB |
**Average: ~200KB per image (all variants)**
## Upload Process
### API Endpoint
```http
POST /api/v1/admin/images/upload
Content-Type: multipart/form-data
file: <binary>
store_id: 123
product_id: 456 (optional, for product images)
type: product|category|banner
```
### Response
```json
{
"success": true,
"image": {
"id": "001a2b3c",
"urls": {
"original": "/uploads/products/00/1a/001a2b3c_original.webp",
"medium": "/uploads/products/00/1a/001a2b3c_800.webp",
"thumb": "/uploads/products/00/1a/001a2b3c_200.webp"
},
"size_bytes": 295000,
"dimensions": {
"width": 1200,
"height": 1200
}
}
}
```
## Configuration
### Environment Variables
```bash
# Image storage configuration
IMAGE_UPLOAD_DIR=/var/www/uploads
IMAGE_MAX_SIZE_MB=10
IMAGE_ALLOWED_TYPES=jpg,jpeg,png,gif,webp
IMAGE_QUALITY=85
IMAGE_MAX_DIMENSION=2000
```
### Python Configuration
```python
# app/core/config.py
class ImageSettings:
UPLOAD_DIR: str = "/static/uploads"
MAX_SIZE_MB: int = 10
ALLOWED_TYPES: list = ["jpg", "jpeg", "png", "gif", "webp"]
QUALITY: int = 85
MAX_DIMENSION: int = 2000
# Generated sizes
SIZES: dict = {
"original": None, # No resize, just optimize
"medium": 800,
"thumb": 200,
}
```
## Performance Guidelines
### Filesystem Limits
| Files per Directory | Status | Action |
|---------------------|--------|--------|
| < 10,000 | OK | None needed |
| 10,000 - 50,000 | Monitor | Plan migration |
| 50,000 - 100,000 | Warning | Increase sharding depth |
| > 100,000 | Critical | Migrate to object storage |
### Capacity Planning
| Products | Images (5/product) | Total Files (3 sizes) | Storage |
|----------|--------------------|-----------------------|---------|
| 10,000 | 50,000 | 150,000 | 30 GB |
| 50,000 | 250,000 | 750,000 | 150 GB |
| 100,000 | 500,000 | 1,500,000 | 300 GB |
| 500,000 | 2,500,000 | 7,500,000 | 1.5 TB |
## CDN Integration
For production deployments, configure a CDN for image delivery:
### Cloudflare (Recommended)
1. Set up Cloudflare for your domain
2. Configure page rules for `/uploads/*`:
- Cache Level: Cache Everything
- Edge Cache TTL: 1 month
- Browser Cache TTL: 1 week
### nginx Configuration
```nginx
location /uploads/ {
alias /var/www/uploads/;
expires 30d;
add_header Cache-Control "public, immutable";
add_header X-Content-Type-Options nosniff;
# WebP fallback for older browsers
location ~ \.(jpg|jpeg|png)$ {
try_files $uri$webp_suffix $uri =404;
}
}
```
## Maintenance
### Cleanup Orphaned Images
Remove images not referenced by any product:
```bash
# Run via admin CLI
python -m scripts.cleanup_orphaned_images --dry-run
python -m scripts.cleanup_orphaned_images --execute
```
### Regenerate Variants
If image quality settings change:
```bash
# Regenerate all variants for a store
python -m scripts.regenerate_images --store-id 123
# Regenerate all variants (use with caution)
python -m scripts.regenerate_images --all
```
## Monitoring
### Metrics to Track
- Total file count
- Storage used (GB)
- Files per directory (max)
- Upload success rate
- Average processing time
### Health Checks
The platform health page includes image storage metrics:
- Current file count
- Storage usage
- Directory distribution
- Processing queue status
## Troubleshooting
### Common Issues
**Upload fails with "File too large"**
- Check `IMAGE_MAX_SIZE_MB` setting
- Verify nginx `client_max_body_size`
**Images not displaying**
- Check file permissions (should be readable by web server)
- Verify URL paths match actual file locations
**Slow uploads**
- Check disk I/O performance
- Consider async processing queue
## Related Documentation
- [Capacity Planning](../architecture/capacity-planning.md)
- [Platform Health](platform-health.md)
- [Capacity Monitoring](capacity-monitoring.md)