1

I am using rails 5.2, Shrine 2.19 and tus server 2.3 for resumable file upload

routes.rb

  mount Tus::Server => '/files'

model, file_resource.rb

class FileResource < ApplicationRecord
  # adds an `file` virtual attribute
  include ResumableFileUploader::Attachment.new(:file)

controllers/files_controller.rb

def create
      file = FileResource.new(permitted_params)
      ...
      file.save

config/initializers/shrine.rb


s3_options = {
  bucket: ENV['S3_MEDIA_BUCKET_NAME'],
  access_key_id: ENV['S3_ACCESS_KEY'],
  secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
  region: ENV['S3_REGION']
}

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'file_library/shrine_cache', **s3_options),
  store: Shrine::Storage::S3.new(**s3_options), # public: true,
  tus: Shrine::Storage::Tus.new
}

Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data

config/initializers/tus.rb

Tus::Server.opts[:storage] = Tus::Storage::S3.new(
  prefix: 'file_library',
  bucket: ENV['S3_MEDIA_BUCKET_NAME'],
  access_key_id: ENV['S3_ACCESS_KEY'],
  secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
  region: ENV['S3_REGION'],
  retry_limit: 3
)
Tus::Server.opts[:redirect_download] = true

My issue is I cannot override the generate_location method of Shrine class to store the files in different folder structure in AWS s3.

All the files are created inside s3://bucket/file_library/ (the prefix provided in tus.rb). I want something like s3://bucket/file_library/:user_id/:parent_id/ folder structure.

I found that Tus configuration overrides all my resumable_file_uploader class custom options and have no effect on uploading.

resumable_file_uploader.rb

class ResumableFileUploader < Shrine
  plugin :validation_helpers  # NOT WORKS
  plugin :pretty_location     # NOT WORKS

  def generate_location(io, context = {})  # NOT WORKS
    f = context[:record]
    name = super # the default unique identifier

    puts "<<<<<<<<<<<<<<<<<<<<<<<<<<<<"*10

    ['users', f.author_id, f.parent_id, name].compact.join('/')
  end

  Attacher.validate do                    # NOT WORKS
    validate_max_size 15 * 1024 * 1024, message: 'is too large (max is 15 MB)'
  end

end

So how can I create custom folder structure in S3 using tus options (as shrine options not works)?

Abhi
  • 3,361
  • 2
  • 33
  • 38

1 Answers1

1

A tus server upload doesn't touch Shrine at all, so the #generate_location won't be called, but instead the tus-ruby-server decides the location.

Note that the tus server should only act as a temporary storage, you should still use Shrine to copy the file to a permanent storage (aka "promote"), just like with regular direct uploads. On promotion the #generate_location method will be called, so the file will be copied to the desired location; this all happens automatically with default Shrine setup.

Janko
  • 8,985
  • 7
  • 34
  • 51
  • Ok, thanks that. I was waiting for ur answer. I will change the options and see. – Abhi May 31 '20 at 13:52
  • First I am sending file to tus endpoint /files and if saves in cache successfully, I am calling the create file API, which does the `file.save`, then It should call the `Shrine` right? – Abhi Jun 01 '20 at 13:51
  • `file.save` takes the tus setup, not shrine. So you prefer after `file.save` do `ResumableFileUploader.upload(file_path)` again to save it in s3 as per shrine configuration? – Abhi Jun 01 '20 at 13:53
  • Yes, if it's not promoting the cached file to permanent storage, please produce a self-contained example that reproduces this behaviour. – Janko Jun 01 '20 at 13:53