Active Storage Resumable allow you to continue an upload even after a browser restart. Currently it only supports Google Cloud Storage.
This library augments Active Storage direct uploads to support resumable uploads with almost identical semantics. If you already uses direct upload, turn it resumable is straightforward.
First setup Active Storage to use GCS.
Add this line to your application's Gemfile:
gem 'activestorage-resumable'
And then execute:
$ bundle
$ rails active_storage_resumable:install:migrations
$ rails db:migrate
Active Storage Resumable, also includes a JavaScript library, that uploads file in chunks, saving the progress in localStorage, allowing to resume an upload even after a browser restart.
-
Export an environment variable called UPLOAD_ORIGIN_URL with the upload origin URL, for example 'http://localhost:3000'. You can also create a
config/initializers/activestorage_resumable.rb
with the following:ActiveStorage::Resumable.configure do |config| config.upload_origin_url = 'https://mydomain.test:3000' end
-
Include
activestorage-resumable.js
in your application's JavaScript bundle.Using the asset pipeline:
//= require activestorage-resumable
Using the npm package:
require("@fnix/activestorage-resumable").start()
-
Annotate file inputs with the resumable upload URL.
<%= form.file_field :attachments, multiple: true, resumable_upload: true %>
-
That's it! Uploads begin upon form submission.
Event name | Event target | Event data (event.detail ) |
Description |
---|---|---|---|
resumable-uploads:start |
<form> |
None | A form containing files for resumable upload fields was submitted. |
resumable-upload:initialize |
<input> |
{id, file} |
Dispatched for every file after form submission. |
resumable-upload:start |
<input> |
{id, file} |
A resumable upload is starting. |
resumable-upload:before-blob-request |
<input> |
{id, file, xhr} |
Before making a request to your application for resumable upload metadata. |
resumable-upload:before-storage-request |
<input> |
{id, file, gcsBrowserUpload} |
Before making a request to store a file. |
resumable-upload:progress |
<input> |
{id, file, progress} |
As requests to store files progress. |
resumable-upload:error |
<input> |
{id, file, error} |
An error occurred. An alert will display unless this event is canceled. |
resumable-upload:end |
<input> |
{id, file} |
A resumable upload has ended. |
resumable-uploads:end |
<form> |
None | All resumable uploads have ended. |
The events are almost identical to Active Storage direct upload. The bigger difference is in before-storage-request
,
instead of a XHR, it uses an Upload object from
@fnix/gcs-browser-upload. Resumable uploads are transfered in
chunks, so it's not very useful to return the XHR of the first chunk. Another small change is in the progress
event
data, it's not a real ProgressEvent, it's only a faker
with the same ProgressEvent properties.
We added three scopes for ActiveStorage::Blob
:
ActiveStorage::Blob.resumable
: Returns all resumable blobs not attached to any model;ActiveStorage::Blob.active_resumable
: Returns all unfinished resumable blobs created in the last week (the duration of a resumable session URI). You can use this to show for your users the uploads that can be resumed;ActiveStorage::Blob.expired_resumable
: This is most for internal use, we use it to cleanup unfinished resumable blobs.
We also added the instance method uploaded_bytes
to ActiveStorage::Blob
so you can show to your users the progress
of unfinished resumable blobs.
The gem is available as open source under the terms of the MIT License.