Files
Ty Clifford 4b4c18f2d9 - Added R2 multipart upload support and streamed fallback uploads in [R2Client.php](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/src/R2/R2Client.php).
Added a shared resumable upload session service in 
[ResumableUploadService.php](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/src/Service/ResumableUploadService.php).
Wired dashboard JSON upload endpoints in 
[AppController.php](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/src/Controller/AppController.php).
Reworked the upload UI/JS to chunk files directly from the browser to 
presigned R2 multipart URLs in 
[app.js](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/public/assets/app.js).
Added the dedicated iPhone/Safari side uploader at 
[side-upload.php](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/public/side-upload.php), 
with its own password and fixed destination prefix via script constants, 
.env, or side-upload.json.
Added 
[side-upload.example.json](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/side-upload.example.json), 
ignored the real side-upload.json, and documented setup/CORS in 
[README.md](/Users/tyemeclifford/Documents/GH/CloudflareR2-Manager/README.md).
2026-06-21 11:24:09 -04:00

135 lines
4.9 KiB
Markdown

# CloudflareR2-Manager
A self-contained PHP web application for managing a Cloudflare R2 bucket with a local SQLite mirror.
## Features
- Simple password authentication with CSRF protection.
- R2 object browser backed by SQLite, so normal navigation uses the local mirror instead of repeatedly listing the bucket.
- Prefix/folder organization, including zero-byte marker objects for empty folders.
- Upload one or more files directly to R2 with local tags, permission labels, and operator notes.
- Resumable browser uploads using R2 multipart upload URLs, suitable for large files and mobile Safari.
- Optional side upload page with its own password and fixed destination prefix for quick iPhone uploads.
- Download, delete, copy, move, rename, and refresh object metadata.
- Generate presigned `GET`, `PUT`, `HEAD`, and `DELETE` URLs.
- Manage bucket CORS from JSON.
- Track local usage events for sync, upload, download, copy, move, delete, CORS, and signed URL generation.
- Optional public URL display for public buckets or custom R2 domains.
## Cloudflare R2 Notes
Cloudflare R2 uses the S3-compatible API at `https://<ACCOUNT_ID>.r2.cloudflarestorage.com` and the S3 region is `auto`.
As of Cloudflare's R2 S3 compatibility docs updated June 8, 2026, S3 ACLs and object tagging APIs are not implemented by R2. This app therefore stores tags, permission labels, and notes locally in SQLite while keeping file bytes in R2. Bucket CORS, object list/get/put/delete/copy, and presigned URLs are handled through R2's S3-compatible API.
## Requirements
- PHP 8.1 or newer.
- PHP extensions: `pdo_sqlite`, `curl`, `simplexml`, `fileinfo`.
- A Cloudflare R2 bucket.
- R2 API credentials with access to that bucket.
Composer is not required.
## Setup
1. Copy the environment example:
```sh
cp .env.example .env
```
2. Edit `.env`:
```dotenv
APP_PASSWORD="choose-a-real-password"
R2_ACCOUNT_ID="your-cloudflare-account-id"
R2_ACCESS_KEY_ID="your-r2-access-key-id"
R2_SECRET_ACCESS_KEY="your-r2-secret-access-key"
R2_BUCKET="your-bucket-name"
```
3. Start the PHP development server:
```sh
php -S 127.0.0.1:8080 -t public
```
4. Open `http://127.0.0.1:8080`, sign in, and run **Sync current prefix**.
## Resumable Uploads
The dashboard upload form uses browser-side R2 multipart uploads when JavaScript is available. PHP creates the multipart upload, signs each part URL, records completed part ETags in `storage/cache/uploads`, and completes the upload when all parts are present. If a connection drops, choose the same file again and the app will reuse the saved multipart session.
Useful settings:
```dotenv
UPLOAD_PART_SIZE=8388608
UPLOAD_PART_URL_TTL=3600
UPLOAD_SESSION_TTL=604800
R2_REQUEST_TIMEOUT=300
```
`UPLOAD_PART_SIZE` is bytes. Keep it at or above `5242880` because S3-compatible multipart uploads require 5 MiB minimum parts except for the last part.
Because file chunks upload from the browser directly to R2, your bucket CORS policy must allow the app origin to `PUT` and expose `ETag`. The default CORS editor example already includes `PUT` and `ETag`; change `AllowedOrigins` to your deployed app origin.
## Side Upload Page
`/side-upload.php` is a narrow upload-only page for quick mobile uploads. It uses a separate password from the main app and always uploads into a configured prefix.
Configure it in `.env`:
```dotenv
SIDE_UPLOAD_PASSWORD="choose-a-different-password"
SIDE_UPLOAD_PREFIX="iphone-uploads/"
SIDE_UPLOAD_TAGS="source=iphone"
```
You can also edit the constants at the top of `public/side-upload.php`. Or copy `side-upload.example.json` to `side-upload.json` and edit the password and prefix there. The real `side-upload.json` file is ignored by git.
## Password Hashes
For a plain setup, use `APP_PASSWORD`. For a hashed password, generate a hash with PHP and set `APP_PASSWORD_HASH` instead:
```sh
php -r 'echo password_hash("your-password", PASSWORD_DEFAULT), PHP_EOL;'
```
## Public URLs
If your bucket has public access or a custom domain, set:
```dotenv
R2_PUBLIC_URL="https://static.example.com"
```
The app will display copyable public links. It does not make a bucket public; public access is controlled in Cloudflare.
## Usage Tracking
The usage dashboard is a local operational ledger. It records actions performed through this app and current mirrored storage size. It is useful for estimating activity, but it is not a replacement for Cloudflare's official billing or analytics.
## CORS Format
Enter CORS as an array of S3-style rules:
```json
[
{
"AllowedOrigins": ["https://example.com"],
"AllowedMethods": ["GET", "PUT", "HEAD"],
"AllowedHeaders": ["Content-Type"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
```
## Security
- Keep `.env` outside version control.
- Serve the app behind HTTPS in production.
- Use least-privilege R2 credentials.
- Restrict access at your web server or VPN if this manages production buckets.