297 lines
8.8 KiB
Markdown
297 lines
8.8 KiB
Markdown
# Image Uploader with Multi-Upload & Slideshow
|
|
|
|
A self-hosted image uploader with multi-image upload capabilities and automatic slideshow functionality.
|
|
|
|
## Features
|
|
|
|
**Multi-Image Upload**: Upload multiple images at once with batch processing
|
|
**Slideshow Mode**: Automatic fullscreen slideshow with smooth transitions
|
|
**Persistent Storage**: Docker volumes ensure data persistence across restarts
|
|
**Clean UI**: Minimalist design focused on user experience
|
|
**Self-Hosted**: Complete control over your data and infrastructure
|
|
**Lightweight**: Built with modern web technologies for optimal performance
|
|
|
|
## What's New
|
|
This project extends the original [Image-Uploader by vallezw](https://github.com/vallezw/Image-Uploader) with enhanced multi-upload and slideshow capabilities.
|
|
|
|
- Multi-image batch upload with progress tracking
|
|
- Automatic slideshow presentation mode
|
|
- Image grouping with descriptions
|
|
- Random slideshow rotation
|
|
- Keyboard navigation support
|
|
- Mobile-responsive design- Mobile-responsive design
|
|
|
|
## Quick Start
|
|
|
|
### Docker Deployment (Recommended)
|
|
|
|
1. **Create docker-compose.yml**:
|
|
|
|
```yaml
|
|
services:
|
|
frontend:
|
|
image: vallezw/image-uploader-client
|
|
ports:
|
|
- "80:80"
|
|
depends_on:
|
|
- backend
|
|
environment:
|
|
- "API_URL=http://localhost:5000"
|
|
- "CLIENT_URL=http://localhost"
|
|
container_name: frontend
|
|
backend:
|
|
image: vallezw/image-uploader-backend
|
|
environment:
|
|
- "CLIENT_URL=http://localhost"
|
|
container_name: backend
|
|
backend:
|
|
image: vallezw/image-uploader-client
|
|
ports:
|
|
- "80:80"
|
|
container_name: frontend
|
|
image: vallezw/image-uploader-backend
|
|
ports:
|
|
- "5000:5000"
|
|
container_name: backend
|
|
volumes:
|
|
- app-data:/usr/src/app/src/upload
|
|
depends_on:
|
|
- app-data:/usr/src/app/src/data
|
|
- backend
|
|
volumes:
|
|
app-data:
|
|
environment:
|
|
- "API_URL=http://localhost:5000"
|
|
- "CLIENT_URL=http://localhost"
|
|
driver: local
|
|
```
|
|
|
|
2. **Start the application**:
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
|
|
3. **Access the application**:
|
|
|
|
- Upload Interface: `http://localhost`
|
|
- Backend: `http://localhost:5000`
|
|
- Slideshow Mode: `http://localhost/slideshow`
|
|
|
|
|
|
|
|
### Multi-Image Upload
|
|
|
|
1. Visit `http://localhost`
|
|
2. Drag & drop multiple images or click to select
|
|
3. Add an optional description for your image collection
|
|
4. Click "Upload Images" to process the batch
|
|
5. Images are automatically grouped for slideshow viewing
|
|
|
|
### Slideshow Mode
|
|
|
|
- **Automatic Access**: Navigate to `http://localhost/slideshow`
|
|
- **Features**:
|
|
- Fullscreen presentation
|
|
- 4-second display per image
|
|
- Automatic progression through all slideshow collections
|
|
- Random selection of next slideshow after completing current one
|
|
- Smooth fade transitions (0.5s)
|
|
|
|
- **Keyboard Controls**:
|
|
- **ESC**: Exit slideshow / Return to upload page
|
|
- **Spacebar / Arrow Right**: Manually advance to next image
|
|
- **Home Button**: Return to main upload interface
|
|
|
|
### Moderation Interface (Protected)
|
|
|
|
- **Access**: `http://localhost/moderation` (requires authentication)
|
|
- **Authentication**: HTTP Basic Auth (username: admin, password: set during setup)
|
|
- **Features**:
|
|
- Review pending image groups before public display
|
|
- Approve or reject submitted collections
|
|
- Delete individual images from approved groups
|
|
- View group details (title, creator, description, image count)
|
|
- Bulk moderation actions
|
|
|
|
- **Group Management**: Navigate to `http://localhost/groups` (requires authentication)
|
|
- Overview of all approved slideshow collections
|
|
- Delete entire groups
|
|
- Launch slideshow mode from any group
|
|
- View group statistics and metadata
|
|
|
|
**Security Features**:
|
|
- Password protected access via nginx HTTP Basic Auth
|
|
- Hidden from search engines (`robots.txt` + `noindex` meta tags)
|
|
- No public links or references in main interface
|
|
|
|
## Data Structure
|
|
### Slideshow JSON Format
|
|
|
|
```json
|
|
[
|
|
{
|
|
"groupId": "0fSwazTOU",
|
|
"description": "My Photo Collection",
|
|
"uploadDate": "2025-10-11T14:34:48.159Z",
|
|
"images":
|
|
{
|
|
"fileName": "ZMmHXzHbqw.jpg",
|
|
"originalName": "vacation-photo-1.jpg",
|
|
"filePath": "/upload/ZMmHXzHbqw.jpg",
|
|
"uploadOrder": 1
|
|
},
|
|
{
|
|
"fileName": "tjjnngOmXS.jpg",
|
|
"originalName": "vacation-photo-2.jpg",
|
|
"filePath": "/upload/tjjnngOmXS.jpg",
|
|
"uploadOrder": 2
|
|
}
|
|
],
|
|
"imageCount": 21
|
|
}
|
|
]
|
|
```
|
|
|
|
### Field Descriptions
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `groupId` | string | Unique identifier generated with shortid |
|
|
| `description` | string | User-provided description for the image collection |
|
|
| `uploadDate` | string | ISO timestamp of upload completion |
|
|
| `images` | array | Array of image objects in the collection |
|
|
| `imageCount` | number | Total number of images in the group |
|
|
|
|
|
|
### Image Object Structure
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `fileName` | string | Generated unique filename for storage |
|
|
| `originalName` | string | Original filename from user's device |
|
|
| `filePath` | string | Relative path to the stored image file |
|
|
| `uploadOrder` | number | Sequential order within the slideshow (1, 2, 3...) |
|
|
|
|
## Architecture
|
|
### Backend (Node.js + Express)
|
|
- **Multi-upload API**: `/api/upload/batch` - Handles batch file processing
|
|
- **Groups API**: `/api/groups` - Retrieves slideshow collections
|
|
- **File Storage**: Organized in `/upload` directory
|
|
- **Metadata Storage**: JSON files in `/data` directory
|
|
|
|
### Frontend (React + Material-UI)
|
|
|
|
- **Multi-Upload Interface**: Drag & drop with preview gallery
|
|
- **Progress Tracking**: Real-time upload status
|
|
- **Spacebar / Arrow Right**: Manually advance to next image
|
|
- **Slideshow Engine**: Fullscreen presentation with automatic progression
|
|
- **Responsive Design**: Mobile and desktop optimized
|
|
- **Home Button**: Return to main upload interface
|
|
|
|
|
|
### Storage Architecture
|
|
|
|
```
|
|
Docker Volume (app-data)
|
|
├── upload/
|
|
│ ├── ZMmHXzHbqw.jpg
|
|
│ ├── tjjnngOmXS.jpg
|
|
│ └── ...### Slideshow JSON Format
|
|
└── data/ # Metadata
|
|
└── upload-groups.json
|
|
```
|
|
|
|
### Hosting it with Docker
|
|
|
|
- **Frontend**: React 17, Material-UI, React Router
|
|
- **Backend**: Node.js, Express, Multer (file handling)
|
|
- **Containerization**: Docker, Docker Compose
|
|
- **Reverse Proxy**: nginx (routing & file serving)[In order to host the project you will need to create a docker-compose file. These files are combining multiple docker images to interact with each other.
|
|
- **File Upload**: Drag & drop with react-dropzone
|
|
- **Notifications**: SweetAlert2
|
|
|
|
## API Endpoints
|
|
### Upload Operations
|
|
|
|
- `POST /api/upload/batch` - Upload multiple images with description
|
|
- `GET /api/groups` - Retrieve all slideshow groups
|
|
- `GET /api/groups/:id` - Get specific slideshow group
|
|
|
|
### Moderation Operations (Protected)
|
|
|
|
- `GET /moderation/groups` - Get all groups pending moderation
|
|
- `POST /groups/:id/approve` - Approve a group for public display
|
|
- `DELETE /groups/:id` - Delete an entire group
|
|
- `DELETE /groups/:id/images/:imageId` - Delete individual image from group
|
|
|
|
### File Access
|
|
- `GET /api/upload/:filename` - Access uploaded image files
|
|
|
|
## Configuration
|
|
### Environment Variables
|
|
|
|
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `API_URL` | `http://localhost:5000` | Backend API endpoint |
|
|
| `CLIENT_URL` | `http://localhost` | Frontend application URL |
|
|
|
|
|
|
### Volume Configuration
|
|
|
|
- **Data Persistence**: `/usr/src/app/src/upload` and `/usr/src/app/src/data` mounted to `app-data`
|
|
- **Upload Limits**: 100MB maximum file size for batch uploads
|
|
- **Supported Formats**: JPG, JPEG, PNG, GIF, WebP
|
|
|
|
|
|
|
|
### Custom Deployment
|
|
For production deployment, modify the docker-compose configuration:
|
|
|
|
```yaml
|
|
|
|
environment:
|
|
|
|
- "API_URL=https://your-domain.com/api"
|
|
|
|
- "CLIENT_URL=https://your-domain.com"
|
|
```
|
|
|
|
|
|
|
|
### Backup & Restore
|
|
#### Backup slideshow data
|
|
```sh
|
|
docker cp backend:/usr/src/app/src/data ./backup-data
|
|
docker cp backend:/usr/src/app/src/upload ./backup-images
|
|
```
|
|
|
|
#### Restore slideshow data
|
|
```sh
|
|
docker cp ./backup-data backend:/usr/src/app/src/data
|
|
docker cp ./backup-images backend:/usr/src/app/src/upload
|
|
```
|
|
|
|
|
|
## Contributing
|
|
Contributions are welcome!
|
|
This project extends the original work by [vallezw](https://github.com/vallezw/Image-Uploader).
|
|
|
|
### Development Setup
|
|
1. Fork the repository
|
|
2. Create feature branch: `git checkout -b feature/amazing-feature`
|
|
3. Commit changes: `git commit -m 'Add amazing feature'`
|
|
4. Push to branch: `git push origin feature/amazing-feature`| Field | Type | Description |#### Changing the URL
|
|
5. Open a Pull Request
|
|
|
|
## License
|
|
This project is distributed under the MIT License. See `LICENSE` for more information.
|
|
|
|
## Acknowledgments
|
|
- Original project: [Image-Uploader by vallezw](https://github.com/vallezw/Image-Uploader)
|
|
|
|
|
|
|
|
|