MultipleUploadJAVASCRIPT · YOUR BACKEND

INTERACTIVE EXAMPLE

Browser-direct Google Cloud Storage resumable upload

Third member of the cloud-direct trio (S3, Azure, GCS). The browser uploads each chunk straight to a GCS resumable session URL via Content-Range headers. Bytes bypass your server entirely - your backend only signs the initiate. Survives reloads via IndexedDB: the resumed task probes GCS with a zero-byte PUT, reads Range: bytes=0-N from the 308 response, and continues from byte N+1.

Resume contract: the GCS session URL is persisted in IndexedDB. On resume, a zero-byte PUT to the session URL with Content-Range: bytes */<total> returns 308 Resume Incomplete with the byte offset GCS holds. The client picks up from there. Identical model to tus.
Client config
new MultipleUpload('#uploader', {
 uploadUrl: '/api/upload',
 strategy: 'gcs',
 chunkSize: 8 * 1024 * 1024, // default 8 MiB; auto-rounded to 256 KiB grain
 persistState: true,
 persistAdapter: 'indexeddb',

 // Optional: override the default endpoint paths
 // gcsInitiateUrl: '/my/gcs/initiate',
 // gcsFinalizeUrl: '/my/gcs/finalize',
 // gcsAbortUrl: '/my/gcs/abort',
});
Wire protocol
  • POST /gcs/initiate - your server creates a GCS resumable session via the official SDK, returns { sessionUrl, key }. The browser never sees the GCS access token.
  • PUT <sessionUrl> <- chunked bytes with Content-Range: bytes <s>-<e>/<total>
  • 308 Resume Incomplete on every chunk except the last (with Range: bytes=0-N showing committed offset)
  • 200/201 OK on the final chunk - body is the GCS object metadata
  • POST /gcs/finalize - your bookkeeping hook (record GCS key in DB, etc.)
Node server snippet (initiate)
// /gcs/initiate handler - using @google-cloud/storage
import { Storage } from '@google-cloud/storage';
const storage = new Storage();
const bucket = storage.bucket('your-bucket');

app.post('/gcs/initiate', async (req, res) => {
 const { fileName, fileSize, contentType } = req.body;
 const file = bucket.file(`uploads/${crypto.randomUUID()}/${fileName}`);
 const [sessionUrl] = await file.createResumableUpload({ metadata: { contentType } });
 res.json({ sessionUrl, key: file.name });
});
Bucket CORS
[{
 "origin": ["https://your-site.com"],
 "method": ["PUT", "OPTIONS"],
 "responseHeader": ["Range", "Content-Range", "ETag"],
 "maxAgeSeconds": 3600
}]

Apply with gsutil cors set cors.json gs://your-bucket.

Cloud trio at a glance
StrategyBest forChunk grainConcurrency
's3'S3, MinIO, R2, B2, Wasabi5 MiB min partParallel parts
'azure'Azure Blob4 MiB blocksParallel blocks
'gcs'Google Cloud Storage256 KiB grainSequential (protocol)

Make it your own.

Start with the example code and connect your application.