JavaScript library for direct file uploads to cloud storage services in Rails applications
npx @tessl/cli install tessl/npm-rails--activestorage@8.0.0Rails Active Storage JavaScript library provides direct file upload functionality to cloud storage services (Amazon S3, Google Cloud Storage, Microsoft Azure Storage) and local disk storage. It enables client-side file uploads without sending files through the Rails application server, improving performance and reducing server load.
npm install @rails/activestorageimport { start, DirectUpload, DirectUploadController, DirectUploadsController, dispatchEvent } from "@rails/activestorage";For CommonJS:
const { start, DirectUpload, DirectUploadController, DirectUploadsController, dispatchEvent } = require("@rails/activestorage");The simplest way to use Active Storage is through automatic form handling:
import { start } from "@rails/activestorage";
// Initialize automatic form handling for direct uploads
start();<!-- HTML form with direct upload enabled -->
<form>
<input type="file" name="attachments" data-direct-upload-url="/rails/active_storage/direct_uploads" multiple>
<button type="submit">Upload Files</button>
</form>For custom upload handling:
import { DirectUpload } from "@rails/activestorage";
const file = document.querySelector("input[type=file]").files[0];
const url = "/rails/active_storage/direct_uploads";
const upload = new DirectUpload(file, url, {
directUploadWillCreateBlobWithXHR(xhr) {
// Called before blob creation request
console.log("Creating blob...");
},
directUploadWillStoreFileWithXHR(xhr) {
// Called before file upload to storage
console.log("Uploading to storage...");
}
});
upload.create((error, blob) => {
if (error) {
console.error("Upload failed:", error);
} else {
console.log("Upload successful:", blob);
// Use blob.signed_id for form submission
}
});Active Storage JavaScript is built around several key components:
start() function that sets up DOM event listenersThe upload process follows this sequence:
Provides seamless integration with Rails forms through automatic event handling and direct upload coordination.
/**
* Initializes Active Storage automatic direct upload handling
* Sets up DOM event listeners for forms with direct upload file inputs
*/
function start(): void;Core functionality for programmatic file uploads with full control over the upload process and event handling.
/**
* Main class for performing direct file uploads to cloud storage
*/
class DirectUpload {
constructor(file: File, url: string, delegate?: DirectUploadDelegate, customHeaders?: Record<string, string>);
create(callback: (error: string | null, blob?: BlobAttributes) => void): void;
readonly id: number;
readonly file: File;
readonly url: string;
}
interface DirectUploadDelegate {
directUploadWillCreateBlobWithXHR?(xhr: XMLHttpRequest): void;
directUploadWillStoreFileWithXHR?(xhr: XMLHttpRequest): void;
}
interface BlobAttributes {
signed_id: string;
key: string;
filename: string;
content_type: string;
byte_size: number;
checksum: string;
}Controller classes for managing upload workflows, event dispatching, and coordinating multiple file uploads within forms.
/**
* Controller for managing individual file uploads with event dispatching
*/
class DirectUploadController {
constructor(input: HTMLInputElement, file: File);
start(callback: (error: string | null) => void): void;
readonly url: string;
}
/**
* Controller for managing multiple file uploads in a form
*/
class DirectUploadsController {
constructor(form: HTMLFormElement);
start(callback: (error?: string) => void): void;
readonly inputs: HTMLInputElement[];
}Helper functions for DOM manipulation, event dispatching, and cross-browser compatibility.
/**
* Dispatches custom DOM events with proper browser compatibility
*/
function dispatchEvent(element: Element, type: string, eventInit?: {
bubbles?: boolean;
cancelable?: boolean;
detail?: any;
}): Event;interface DirectUploadEventDetail {
id: number;
file: File;
error?: string;
progress?: number;
xhr?: XMLHttpRequest;
}
interface DirectUploadEvents {
"direct-uploads:start": { detail: {} };
"direct-uploads:end": { detail: {} };
"direct-upload:initialize": { detail: DirectUploadEventDetail };
"direct-upload:start": { detail: DirectUploadEventDetail };
"direct-upload:before-blob-request": { detail: DirectUploadEventDetail };
"direct-upload:before-storage-request": { detail: DirectUploadEventDetail };
"direct-upload:progress": { detail: DirectUploadEventDetail };
"direct-upload:error": { detail: DirectUploadEventDetail };
"direct-upload:end": { detail: DirectUploadEventDetail };
}