Image Hosting
Multiforum uses Google Cloud Storage (GCS) for hosting uploaded images and files. This guide covers setting up and configuring file storage for your instance.
Overview
The file upload system provides:
- Signed URLs - Time-limited upload access (15 minutes)
- File Type Validation - Server and channel-level restrictions
- Virus Scanning - Optional malware detection
- Image Moderation - Archive and removal workflows
Setting Up Google Cloud Storage
1. Create a Google Cloud Project
- Go to Google Cloud Console
- Create a new project or select an existing one
- Note your project ID
2. Enable the Cloud Storage API
- Go to APIs & Services → Library
- Search for "Cloud Storage"
- Click Enable on the Cloud Storage API
3. Create a Storage Bucket
- Go to Cloud Storage → Buckets
- Click Create Bucket
- Configure your bucket:
- Name: Choose a globally unique name (e.g.,
your-app-uploads) - Location: Choose a region near your users
- Storage class: Standard (recommended)
- Access control: Fine-grained
- Name: Choose a globally unique name (e.g.,
- Click Create
4. Configure CORS
For browser uploads to work, configure CORS on your bucket:
[
{
"origin": ["https://your-frontend-domain.com"],
"method": ["GET", "PUT", "POST", "DELETE"],
"responseHeader": ["Content-Type"],
"maxAgeSeconds": 3600
}
]
Apply using gsutil:
gsutil cors set cors.json gs://your-bucket-name
5. Create a Service Account
- Go to IAM & Admin → Service Accounts
- Click Create Service Account
- Name it (e.g.,
multiforum-storage) - Grant the Storage Admin role
- Create and download a JSON key
6. Encode the Credentials
Base64 encode your service account key:
base64 -i your-service-account-key.json
Save this encoded string for your environment variables.
Environment Variables
Backend
GCS_BUCKET_NAME=your-bucket-name
GOOGLE_CREDENTIALS_BASE64=your-base64-encoded-credentials
Frontend
VITE_GOOGLE_CLOUD_STORAGE_BUCKET=your-bucket-name
File Type Configuration
Server-Level Allowed File Types
Configure default allowed file types in the ServerConfig:
MATCH (s:ServerConfig {serverName: "your-server"})
SET s.allowedFileTypes = [".stl", ".obj", ".zip", ".rar", ".blend", ".png", ".jpg", ".gif"]
Channel-Level Overrides
Individual channels can override server defaults:
- Go to Channel Settings → Downloads
- Edit the Allowed File Types list
- Save changes
Channels can be more restrictive than the server default but not less.
How Uploads Work
Upload Flow
- User selects a file to upload
- Frontend requests a signed URL from the backend
- Backend validates:
- User authentication
- File type allowed
- Channel permissions (if applicable)
- Backend generates a time-limited signed URL
- Frontend uploads directly to GCS using the signed URL
- Frontend notifies backend of successful upload
- Backend creates the Image/File record in the database
Signed URL Security
- URLs expire after 15 minutes
- Each URL is specific to one file
- URLs include authentication tokens
- Direct bucket access is not allowed
Image Features
Image Properties
| Property | Description |
|---|---|
url | The public URL of the image |
alt | Alternative text for accessibility |
caption | Optional caption displayed with image |
longDescription | Extended description for screen readers |
copyright | Copyright information |
hasSensitiveContent | Flag for adult/sensitive content |
hasSpoiler | Flag for spoiler content |
Image Scanning
Images can be scanned for malware and inappropriate content:
| Status | Description |
|---|---|
PENDING | Awaiting scan |
CLEAN | Passed all scans |
INFECTED | Malware detected |
SUSPICIOUS | Flagged for review |
FAILED | Scan failed |
Image Moderation
Moderators can:
- Archive - Hide image from public view
- Permanently Remove - Delete image and purge from storage
- Report - Create a moderation issue for review
All moderation actions are linked to Issues for audit trails.
Enabling Image Uploads Per Channel
Channels can individually enable or disable image uploads:
- Go to Channel Settings
- Find Image Uploads Enabled
- Toggle on/off
- Save changes
Related channel settings:
imageUploadsEnabled- Allow direct image uploadsmarkdownImagesEnabled- Allow embedding images via markdown URLsemojiEnabled- Allow emoji reactions
File Versioning
Downloadable files support version history:
- Each version tracks filename, size, and changelog
- Users can download previous versions
- Version history is preserved
Troubleshooting
Upload Failures
- Verify GCS bucket exists and is accessible
- Check service account has Storage Admin role
- Verify CORS configuration
- Check file type is allowed
- Verify base64 encoding of credentials
CORS Errors
If you see CORS errors in the browser console:
- Verify CORS configuration includes your frontend domain
- Check that the request method is allowed
- Ensure Content-Type header is permitted
Permission Denied
- Check user has
canUploadFilepermission - Verify channel allows uploads (
imageUploadsEnabled) - Check file type is in allowed list