Skip to content

Control file uploads via presigned URLs to cloud storage services

License

Notifications You must be signed in to change notification settings

denisstael/presigned_upload

Repository files navigation

PresignedUpload

Control file uploads via presigned URLs to cloud storage services.

A presigned URL is generated by a server that grants temporary and controlled access to a specific resource. In the context of file uploads, it allows clients to directly upload files to a designated storage location without the server being directly involved in the transfer process.

Installation

1. Add the gem into your project

Add this to your Gemfile and run bundle install.

gem 'presigned_upload'

Or install it yourself as:

gem install presigned_upload

2. Create the initializer file

Run the generator to create the initializer file:

rails g presigned_upload:install

3. Generate Uploadable Model

Use the PresignedUpload generator to create your uploadable model.

This model is intended to be a representation of access to a file, and also its basic informations.

For example, if you want create a UploadLink model, you can use:

rails g presigned_upload:uploadable_model UploadLink

If your database uses UUID for the primary and foreign keys, you can pass the --uuid option:

rails g presigned_upload:uploadable_model UploadLink --uuid

The generator will create the model with the given name and the migration file:

# app/models/upload_link.rb
class UploadLink < ApplicationRecord
  presigned_uploadable_model
end

# This columns are required, but you can add more if you need.
# For example, you can create a column called 'storage_size'
#  to save the storage size of the file
class CreateUploadLinks < ActiveRecord::Migration[7.0]
  def change
    create_table :upload_links, id: :uuid do |t|
      t.string :original_name, null: false
      t.string :content_type, null: false
      t.string :upload_status, null: false

      t.timestamps
    end
  end
end

By default, an uploadable model contains:

  • original_name: The original name of the file
  • content_type: The content-type of the file (Utile for validations)
  • upload_status: The status of the upload process [initial, completed]

4. Run the migration

rails db:migrate

Usage

Configuring initializer

You can configure the presigned_upload initializer to set the storage service and its options.

For AWS S3 for example, you going to need to add the storage to :aws and inform the bucket where you want to create presigned URLs in order to upload and access files:

PresignedUpload.configure do |config|
  config.storage = :aws
  config.storage_options = {
    bucket: 'my_bucket'
  }
end

Important: For an AWS configuration, you need to add the AWS SDK for Ruby in order to PresignedUpload gem to work correctly:

gem 'aws-sdk-s3'

If you don't add this, an error will be raised when trying to run Rails.

Uploadable Model

The uploadable model will be used to access files in the cloud storage services. Below there are some of the methods that can be accessed:

# Returns a presigned URL for uploading the file
# Only returns the URL if the upload_status is 'initial'
upload_link.upload_url

# Returns a presigned URL for accessing the stored file
# Only returns the URL if the upload_status is 'completed'
upload_link.url

# Deletes the stored file from the cloud
# This method is automatically called in before_destroy 
#   callback when you destroy the record
upload_link.delete_stored_file

In order to be able to use this methods, you need to configure the store directory where the file will be stored.

Storage path

By default, PresignedUpload inserts the method presigned_uploadable_model in your Model, that sets the value of the store_dir to: "uploads/#{model_name.plural}/#{id}".

The final store_path of the file in the cloud will be the junction between store_dir + original_name.

So, in the example below, the file will be stored as uploads/upload_links/123/my_file.txt:

class UploadLink < ApplicationRecord
  presigned_uploadable_model
end

upload_link.id = '123'
upload_link.original_name = 'my_file.txt'
upload_link.store_path
# => uploads/upload_links/123/my_file.txt

Changing the storage directory

The presigned_uploadable_model method accepts the :store_dir option, that can be a Symbol, a String or a Proc.

Using a string:

class UploadLink < ApplicationRecord
  presigned_uploadable_model store_dir: '/uploads/my/custom/path'
end

upload_link.original_name = 'my_file.txt'
upload_link.store_path
# => "/uploads/my/custom/path/my_file.txt"

Using a Proc:

class UploadLink < ApplicationRecord
  presigned_uploadable_model store_dir: -> { "/uploads/upload_links/#{id}" }
end

upload_link.id = '123'
upload_link.original_name = 'my_file.txt'
upload_link.store_path
# => "/uploads/upload_links/123/my_file.txt"

Using a Symbol:

class UploadLink < ApplicationRecord
  presigned_uploadable_model store_dir: :my_custom_dir

  # Using as a symbol, the code will expect a instance method with same name
  def my_custom_dir
    "/my/custom/dir/#{id}"
  end
end

upload_link.id = '123'
upload_link.original_name = 'my_file.txt'
upload_link.store_path
# => "/my/custom/dir/123/my_file.txt"

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/denisstael/presigned_upload.

License

The gem is available as open source under the terms of the MIT License.

About

Control file uploads via presigned URLs to cloud storage services

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages