Skip to content

Instantly share code, notes, and snippets.

@patorash
Last active January 26, 2017 01:47
Show Gist options
  • Save patorash/160e184596bc648733e2b14a604d429c to your computer and use it in GitHub Desktop.
Save patorash/160e184596bc648733e2b14a604d429c to your computer and use it in GitHub Desktop.
Custom binding of knockout.js using jQueryFileUpload.
<!-- app/views/foos/_form.html.erb -->
<%= file_field_tag '',
style: 'display: none',
data: {
bind: "s3DirectUpload: { start: start_direct_upload, done: finished_direct_upload, fail: failed_direct_upload, progressall: progress_direct_upload }",
'form-data': @s3_direct_post.fields,
url: @s3_direct_post.url,
host: Url.parse(@s3_direct_post.url).host
} %>
# config/initializers/aws.rb
Aws.config.update({
region: 'ap-northeast-1',
credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']),
})
S3_BUCKET = Aws::S3::Resource.new.bucket(ENV['S3_BUCKET'])
# app/assets/javascripts/view_models/foo_view_model.js.coffee
class @FooViewModel
constructor: ->
@uploading = false
ko.track(this)
start_direct_upload: (e) =>
console.log("jQueryFileUpload: start")
@uploading = true
finished_direct_upload: (e, data) =>
console.log("jQueryFileUpload: done")
s3_object_key = $(data.jqXHR.responseXML).find('Key').text()
form_data = new FormData()
form_data.append('foo[s3_object_key]', s3_object_key)
self = this
$.ajax(
"dummy_url",
type: 'POST',
data: form_data,
processData: false,
contentType: false
).done (data) ->
self.uploading = false
failed_direct_upload: (e, data) =>
console.log("jQueryFileUpload: failed")
@uploading = false
progress_direct_upload: (e, data) =>
progress = parseInt(data.loaded / data.total * 100, 10);
console.log("jQueryFileUpload: uploading... #{progress}%")
$ ->
ko.applyBindings(new FooViewModel())
# app/controllers/foos_controller.rb
class FoosController < ApplicationController
include S3DirectUploadBeforeAction
before_action -> { set_s3_direct_post("files") }, only: [:new, :edit, :create, :update]
def new
# omit
end
def create
# omit
end
def edit
# omit
end
def update
# omit
end
end
# app/assets/javascripts/handlers/s3_direct_upload.js.coffee
ko.bindingHandlers.s3DirectUpload = {
init: (element, valueAccessor, allBindings, viewModel, bindingContext) ->
value = ko.utils.unwrapObservable(valueAccessor())
if value
fileInput = $(element)
fileInput.fileupload(
fileInput: fileInput
url: fileInput.data('url')
type: 'POST'
autoUpload: true
formData: fileInput.data('form-data')
paramName: 'file'
dataType: 'XML'
replaceFileInput: false
progressall: (e, data) ->
value.progressall(e, data) if value.progressall?
start: (e) ->
value.start(e) if value.start?
done: (e, data) ->
value.done(e, data) if value.done?
fail: (e, data) ->
value.fail(e,data) if value.fail?
)
}
concern :S3DirectUploadBeforeAction do
private def set_s3_direct_post(directory_name)
@s3_direct_post = S3_BUCKET.presigned_post(key: "#{directory_name}/#{SecureRandom.uuid}/${filename}",
success_action_status: '201',
acl: 'private')
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment