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

React, Vue & Angular

The Tag Helper is a convenience wrapper: everything it renders can be created with CoreUpload.create(element, options). That is the whole integration story for a SPA — plus knowing when to destroy the instance.

First-party adapters ship in the package: the NuGet package includes useUploader() for React and Vue, a Svelte action and an Angular service under _content/CoreUpload/adapters/<framework>/ (with TypeScript definitions). They resolve the loaded window.CoreUpload global automatically. The patterns below use the plain JS API, which the adapters wrap.

React

function Uploader() {
  const host = useRef(null);
  const [status, setStatus] = useState('');

  useEffect(() => {
    const u = CoreUpload.create(host.current, {
      uploadUrl: '/api/upload/upload',
      chunked: true,
      persistState: true
    });
    u.on('taskProgress', t => setStatus(`${t.fileName}: ${t.progress}%`));
    u.on('taskComplete', (t, r) => setStatus(`${t.fileName} → ${r.fileGuid}`));
    return () => u.destroy();          // strict-mode double-mount safe
  }, []);

  return <><div ref={host} /><p>{status}</p></>;
}

Vue 3

<script setup>
const host = ref(null);
let uploader;
onMounted(() => {
  uploader = CoreUpload.create(host.value, { uploadUrl: '/api/upload/upload', chunked: true });
});
onBeforeUnmount(() => uploader?.destroy());
</script>

<template><div ref="host"></div></template>

Angular

@Component({ selector: 'app-uploader', template: '<div #host></div>' })
export class UploaderComponent implements AfterViewInit, OnDestroy {
  @ViewChild('host') host!: ElementRef;
  private uploader: any;

  ngAfterViewInit() {
    this.uploader = (window as any).CoreUpload.create(this.host.nativeElement, {
      uploadUrl: '/api/upload/upload', chunked: true
    });
  }
  ngOnDestroy() { this.uploader?.destroy(); }
}

The three rules that matter

  • Create once per mount, destroy on unmount. destroy() removes listeners, timers and cross-tab plumbing — skipping it leaks all three under hot-reload.
  • Send auth with the request, not the constructor. The headers option accepts a function evaluated per request, so short-lived JWTs stay fresh: headers: () => ({ Authorization: 'Bearer ' + getToken() }).
  • Cross-origin APIs need CORS on the API, and for direct-to-cloud also on the bucket — see the direct-to-cloud guide.