blackchestnut / blackchestnut.github.io

Developer notes about Ruby on Rails, React Native, PostgreSQL, etc.
https://kalinichev.net
4 stars 0 forks source link

Shrine direct uploads to s3 #8

Open blackchestnut opened 7 years ago

blackchestnut commented 7 years ago

Docs

Shrine - Direct Uploads to S3 Demo Rails Project

Dependencies

jquery.fileupload.js jquery.ui.widget

Example

# Gemfile
gem 'roda'
# app/services/image_uploader.rb
class ImageUploader < Shrine
  plugin :direct_upload
end
/ app/views/teams/new.html.slim
= form_for @team do |f|
  label Logo
  .logo style="background-image: url('#{@team.image_url}');"
  a onclick='$(".upload").click();' Add image

  = f.hidden_field :image, value: @team.cached_image_data
  input.upload.hidden [
    type='file'
    name='file'
    data-dest-selector='#team_image'
    data-preview-selector='.logo'
  ]

  .actions
    = f.submit 'Save'
# app/assets/javascripts/application.coffee
#= require jquery.ui.widget
#= require jquery.fileupload
# app/assets/javascripts/global.coffee
$uploads = $('.upload:not(.listened)')
$uploads.addClass('listened')
$uploads.each (i, elem) ->
  $(elem).fileupload
    add: (e, data) ->
      console.log("Add file - #{data.files[0].name}") # Debug only
      options =
        extension: data.files[0].name.match(/(\.\w+)?$/)[0] # Set extension
        _: Date.now() # Prevent caching
      $.getJSON '/images/cache/presign', options, (result) ->
        data.formData = result['fields']
        data.url = result['url']
        data.paramName = 'file'
        data.submit()
        return
      return
    progress: (e, data) ->
      progress = parseInt(data.loaded / data.total * 100, 10)
      percentage = progress.toString() + '%'
      console.log(percentage) # Debug only
      return
    done: (e, data) ->
      image =
        id: data.formData.key.match(/cache\/(.+)/)[1]
        storage: 'cache'
        metadata:
          size: data.files[0].size
          filename: data.files[0].name.match(/[^\/\\]+$/)[0]
          mime_type: data.files[0].type

      cached_image_url = "#{data.url}/#{data.formData.key}" # For preview
      console.log(image) # Debug only
      console.log(data.formData) # Debug only
      console.log(cached_image_url) # Debug only

      $upload = $(elem)
      $($upload.attr('data-dest-selector')).val(JSON.stringify(image)) # Save image data
      $($upload.attr('data-preview-selector')).
        css('background-image', "url('#{cached_image_url}')") # Show cached image
      return
# config/routes.rb
Rails.application.routes.draw do
  # ...
  mount ImageUploader::UploadEndpoint => '/images'
end