Direct-to-S3 / Azure tus 1.0 resume IndexedDB Golden Retriever 30 locales Webcam & screen capture

Custom strategy via CoreUpload.registerStrategy()

Built-in strategies (single / chunked / s3 / azure / tus / urlImport) cover the common transports. For everything else - signed-GCS multipart, a custom protocol against a legacy backend, WebRTC-style peer upload - register your own strategy. A strategy is just an object with an upload(task, uploader) method that returns a Promise.

What you should see: a pluggable transport standing in for the real one, so you can watch the strategy hooks fire without a server. Auto-upload is off; press upload to step through it.
Drag & drop files here, or paste from clipboard
What this demo does: registers a fake simulated strategy that emits progress without sending bytes, proving the registry works without needing a special backend. Swap the body for real XHR/fetch calls to your own service.

Strategy contract

CoreUpload.registerStrategy('my-transport', {
 upload: function (task, uploader) {
 // Must honour task.abortController for cancel + pause. // Must call uploader._updateProgress(task, loaded, total) to advance UI. // Must resolve with an UploadResult-shaped object, or reject. return fetch('/my-endpoint', {
 method: 'POST',
 body: task.file,
 signal: task.abortController.signal
 }).then(function (r) {
 return r.json();
 });
 },
 name: 'my-transport' // shown in task.metadata.strategy
});

// Use it:
CoreUpload.create('#uploader', {
 strategy: 'my-transport'
});

When to roll your own

  • Your backend expects a protocol CoreUpload doesn't ship (GCS resumable, custom chunk headers, long-polling).
  • You need to inject auth-rotation, signed headers per request, or custom retry semantics.
  • You want to wrap an existing SDK (@aws-sdk/client-s3, Uppy's internal uploader, etc.) with CoreUpload's UI + progress model.
  • You need WebRTC / peer upload / P2P transport.

Inline strategy objects

You can also pass a strategy object directly - no registry call needed:

CoreUpload.create('#uploader', {
 strategy: { name: 'inline', upload: function (task, uploader) { /* ... */ } }
});