s3-upnow 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 731e98ac15afe2b0944cb3b6669f03a4a7771538
4
- data.tar.gz: 56b0c073f0b216026c4fe532d8febd26639fea5a
3
+ metadata.gz: c130dadc4b2ed0be86811b4b029c7539a3265cd8
4
+ data.tar.gz: a8c1aba09a3f422360bbe1abdc5b58f151a7dab4
5
5
  SHA512:
6
- metadata.gz: b9f9d5f7769adbec1d986daa9d3713ef6addd2d217791a63b449ecd6e2898f36849d60415d5b306eaabafb2367b8169577859687c29116be26d1ab4b510fc206
7
- data.tar.gz: ed9c53695746ca26102c18185583d201ff9c00bb93ffe6a7c9802e50c20f82d53fc42a670b870dc7552690df611cb30170cdf5b9f24ba2e994531b684da58d55
6
+ metadata.gz: f3936e913d8dbeb45fea532dc0c1dbb7d6ce2871b404acfb8b685f8920a473b8bb336f87b525bca0fd18971af5b73c290a75b5bdab9791c8c9e0cf57904fbde0
7
+ data.tar.gz: 136f94792ef3951b6e58212b6a42f460e42fca936bb6efc6c8a7c44c06797aebafefb422be88bf35f4a9adcba794d308bdce7e8d2de42b6cd542b70e136e9165
@@ -0,0 +1,50 @@
1
+ $(document).on 'change', (e) ->
2
+ input = $(e.target)
3
+ if (input.prop('tagName') == "INPUT" && input.prop('type') == "file" && input.data('upnow'))
4
+ return if (!input.prop('files'))
5
+ file = input.prop('files')[0]
6
+ file.unique_id = Math.random().toString(36).substr(2,16)
7
+
8
+ dispatchEvent = (name, detail) ->
9
+ ev = document.createEvent('CustomEvent')
10
+ ev.initCustomEvent(name, true, false, detail)
11
+ input[0].dispatchEvent(ev)
12
+
13
+ if (file)
14
+ url = input.data('url')
15
+ fields = input.data('fields')
16
+
17
+ data = new FormData()
18
+
19
+ if (fields)
20
+ Object.keys(fields).forEach (key) ->
21
+ if key == 'key'
22
+ fields[key] = fields[key]
23
+ .replace('{timestamp}', new Date().getTime())
24
+ .replace('{unique_id}', file.unique_id)
25
+ data.append(key, fields[key])
26
+ data.append('content-type', file.type)
27
+ data.append('file', file)
28
+
29
+ xhr = new XMLHttpRequest()
30
+ xhr.addEventListener('load', (e) ->
31
+ input.removeClass('uploading')
32
+ dispatchEvent('upload:complete', xhr.response)
33
+ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304)
34
+ key = input.data('key') || $(xhr.response).find('Key').text()
35
+ input.prev().val(key)
36
+ input.removeAttr('name')
37
+ dispatchEvent('upload:success', xhr.response)
38
+ else
39
+ dispatchEvent('upload:failure', xhr.response)
40
+ )
41
+
42
+ xhr.upload.addEventListener('progress', (e) ->
43
+ dispatchEvent('upload:progress', e) if (e.lengthComputable)
44
+ )
45
+
46
+ xhr.open('POST', url, true)
47
+ xhr.send(data)
48
+
49
+ input.addClass('uploading')
50
+ dispatchEvent('upload:start')
@@ -10,4 +10,6 @@ require 's3-upnow/form_helper'
10
10
  require 's3-upnow/engine' if defined?(Rails)
11
11
  require 's3-upnow/railtie' if defined?(Rails)
12
12
 
13
- ActionView::Base.send(:include, S3UpNow::UploadHelper) if defined?(ActionView::Base)
13
+ module S3UpNow
14
+ autoload :Paperclip, 's3-upnow/paperclip'
15
+ end
@@ -1,4 +1,8 @@
1
1
  module S3UpNow
2
2
  class Engine < ::Rails::Engine
3
+ initializer "s3-upnow.setup", before: :load_environment_config do
4
+ ActionView::Base.send(:include, S3UpNow::S3UpNowHelper) if defined?(ActionView::Base)
5
+ ActionView::Helpers::FormBuilder.send(:include, S3UpNow::S3UpNowFieldHelper)
6
+ end
3
7
  end
4
8
  end
@@ -1,97 +1,22 @@
1
+ require 's3-upnow/generator'
2
+
1
3
  module S3UpNow
2
- module UploadHelper
3
- def s3_uploader_form(options = {}, &block)
4
- uploader = S3Uploader.new(options)
5
- form_tag(uploader.url, uploader.form_options) do
6
- uploader.fields.map do |name, value|
7
- hidden_field_tag(name, value)
8
- end.join.html_safe + capture(&block)
9
- end
4
+ module S3UpNowHelper
5
+ def s3_upnow_field(object_name, method, options = {})
6
+ generator = S3UpNow::Generator.new(options)
7
+ options[:data] ||= {}
8
+ options[:data][:upnow] = true
9
+ options[:data][:url] = generator.url
10
+ options[:data][:fields] = generator.fields
11
+ hidden_field(object_name, :"#{method}_s3_key", options.slice(:object)) +
12
+ file_field(object_name, method, options)
10
13
  end
14
+ end
11
15
 
12
- class S3Uploader
13
- def initialize(options)
14
- @key_starts_with = options[:key_starts_with] || "uploads/"
15
- @options = options.reverse_merge(
16
- aws_access_key_id: S3UpNow.config.access_key_id,
17
- aws_secret_access_key: S3UpNow.config.secret_access_key,
18
- bucket: options[:bucket] || S3UpNow.config.bucket,
19
- region: S3UpNow.config.region || "s3",
20
- url: S3UpNow.config.url,
21
- ssl: true,
22
- acl: "public-read",
23
- expiration: 10.hours.from_now.utc.iso8601,
24
- max_file_size: 500.megabytes,
25
- callback_method: "POST",
26
- callback_param: "file",
27
- key_starts_with: @key_starts_with,
28
- key: key
29
- )
30
- end
31
-
32
- def form_options
33
- {
34
- id: @options[:id],
35
- class: @options[:class],
36
- method: "post",
37
- authenticity_token: false,
38
- multipart: true,
39
- data: {
40
- callback_url: @options[:callback_url],
41
- callback_method: @options[:callback_method],
42
- callback_param: @options[:callback_param]
43
- }.reverse_merge(@options[:data] || {})
44
- }
45
- end
46
-
47
- def fields
48
- {
49
- :key => @options[:key] || key,
50
- :acl => @options[:acl],
51
- "AWSAccessKeyId" => @options[:aws_access_key_id],
52
- :policy => policy,
53
- :signature => signature,
54
- :success_action_status => "201",
55
- 'X-Requested-With' => 'xhr'
56
- }
57
- end
58
-
59
- def key
60
- @key ||= "#{@key_starts_with}{timestamp}-{unique_id}-#{SecureRandom.hex}/${filename}"
61
- end
62
-
63
- def url
64
- @options[:url] || "http#{@options[:ssl] ? 's' : ''}://#{@options[:region]}.amazonaws.com/#{@options[:bucket]}/"
65
- end
66
-
67
- def policy
68
- Base64.encode64(policy_data.to_json).gsub("\n", "")
69
- end
70
-
71
- def policy_data
72
- {
73
- expiration: @options[:expiration],
74
- conditions: [
75
- ["starts-with", "$utf8", ""],
76
- ["starts-with", "$key", @options[:key_starts_with]],
77
- ["starts-with", "$x-requested-with", ""],
78
- ["content-length-range", 0, @options[:max_file_size]],
79
- ["starts-with","$content-type", @options[:content_type_starts_with] ||""],
80
- {bucket: @options[:bucket]},
81
- {acl: @options[:acl]},
82
- {success_action_status: "201"}
83
- ] + (@options[:conditions] || [])
84
- }
85
- end
86
-
87
- def signature
88
- Base64.encode64(
89
- OpenSSL::HMAC.digest(
90
- OpenSSL::Digest.new('sha1'),
91
- @options[:aws_secret_access_key], policy
92
- )
93
- ).gsub("\n", "")
94
- end
16
+ module S3UpNowFieldHelper
17
+ def s3_upnow_field(method, options = {})
18
+ self.multipart = true
19
+ @template.s3_upnow_field(@object_name, method, objectify_options(options))
95
20
  end
96
21
  end
97
22
  end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+
3
+ module S3UpNow
4
+ class Generator
5
+ def initialize(options)
6
+ @key_starts_with = options[:key_starts_with] || "uploads/"
7
+ @options = options.reverse_merge(
8
+ aws_access_key_id: S3UpNow.config.access_key_id,
9
+ aws_secret_access_key: S3UpNow.config.secret_access_key,
10
+ bucket: options[:bucket] || S3UpNow.config.bucket,
11
+ region: S3UpNow.config.region || "s3",
12
+ url: S3UpNow.config.url,
13
+ ssl: true,
14
+ acl: "public-read",
15
+ expiration: 10.hours.from_now.utc.iso8601,
16
+ max_file_size: 500.megabytes,
17
+ callback_method: "POST",
18
+ callback_param: "file",
19
+ key_starts_with: @key_starts_with,
20
+ key: key
21
+ )
22
+ end
23
+
24
+ def fields
25
+ {
26
+ :utf8 => '✓',
27
+ :key => @options[:key] || key,
28
+ :acl => @options[:acl],
29
+ "AWSAccessKeyId" => @options[:aws_access_key_id],
30
+ :policy => policy,
31
+ :signature => signature,
32
+ :success_action_status => "201",
33
+ 'X-Requested-With' => 'xhr'
34
+ }
35
+ end
36
+
37
+ def key
38
+ @key ||= "#{@key_starts_with}{timestamp}-{unique_id}-#{SecureRandom.hex}/${filename}"
39
+ end
40
+
41
+ def url
42
+ @options[:url] || "http#{@options[:ssl] ? 's' : ''}://#{@options[:region]}.amazonaws.com/#{@options[:bucket]}/"
43
+ end
44
+
45
+ def policy
46
+ Base64.encode64(policy_data.to_json).gsub("\n", "")
47
+ end
48
+
49
+ def policy_data
50
+ {
51
+ expiration: @options[:expiration],
52
+ conditions: [
53
+ ["starts-with", "$utf8", ""],
54
+ ["starts-with", "$key", @options[:key_starts_with]],
55
+ ["starts-with", "$x-requested-with", ""],
56
+ ["content-length-range", 0, @options[:max_file_size]],
57
+ ["starts-with","$content-type", @options[:content_type_starts_with] ||""],
58
+ {bucket: @options[:bucket]},
59
+ {acl: @options[:acl]},
60
+ {success_action_status: "201"}
61
+ ] + (@options[:conditions] || [])
62
+ }
63
+ end
64
+
65
+ def signature
66
+ Base64.encode64(
67
+ OpenSSL::HMAC.digest(
68
+ OpenSSL::Digest.new('sha1'),
69
+ @options[:aws_secret_access_key], policy
70
+ )
71
+ ).gsub("\n", "")
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,61 @@
1
+ module S3UpNow
2
+ module Paperclip
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.class_eval do
6
+ private
7
+
8
+ def s3_upnow_attachment(name)
9
+ send(name)
10
+ end
11
+
12
+ def s3_upnow_destination_bucket(name)
13
+ s3_upnow_attachment(name).options[:bucket].call
14
+ end
15
+
16
+ def s3_upnow_destination_path(name)
17
+ s3_upnow_attachment(name).path[1..-1]
18
+ end
19
+
20
+ def s3_upnow_destination_permissions(name)
21
+ s3_upnow_attachment(name).s3_permissions
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ module ClassMethods
28
+ def has_attached_file(name, options = {})
29
+ puts "here"
30
+ self.class_eval do
31
+ attr_accessor "#{name}_s3_key"
32
+
33
+ before_validation "s3_upnow_copy_metadata_from_#{name}".to_sym, unless: "#{name}_s3_key.blank?"
34
+ after_save "s3_upnow_copy_file_from_#{name}".to_sym, unless: "#{name}_s3_key.blank?"
35
+
36
+ private
37
+
38
+ define_method "s3_upnow_copy_metadata_from_#{name}" do
39
+ s3 = AWS::S3.new
40
+ s3_head = s3.buckets[S3UpNow.config.bucket].objects[instance_variable_get("@#{name}_s3_key")].head
41
+
42
+ s3_upnow_attachment(name).clear
43
+ self.send "#{name}_file_name=", File.basename(instance_variable_get("@#{name}_s3_key"))
44
+ self.send "#{name}_file_size=", s3_head.content_length
45
+ self.send "#{name}_content_type=", s3_head.content_type
46
+ self.send "#{name}_updated_at=", s3_head.last_modified
47
+ end
48
+
49
+ define_method "s3_upnow_copy_file_from_#{name}" do
50
+ s3 = AWS::S3.new
51
+ orig_bucket = s3.buckets[S3UpNow.config.bucket]
52
+ orig_object = orig_bucket.objects[instance_variable_get("@#{name}_s3_key")]
53
+ dest_bucket = s3.buckets[s3_upnow_destination_bucket(name)]
54
+ dest_object = dest_bucket.objects[s3_upnow_destination_path(name)]
55
+ dest_object.copy_from(orig_object, acl: s3_upnow_destination_permissions(name))
56
+ end
57
+ end
58
+ super(name, options)
59
+ end
60
+ end
61
+ end
@@ -1,6 +1,9 @@
1
1
  module S3UpNow
2
2
  class Railtie < Rails::Railtie
3
- initializer "railtie.configure_rails_initialization" do |app|
3
+ initializer "railtie.configure_rails_initialization", after: "paperclip.insert_into_active_record" do |app|
4
+ if defined?(ActiveRecord) and defined?(Paperclip)
5
+ ActiveRecord::Base.send(:include, S3UpNow::Paperclip)
6
+ end
4
7
  app.middleware.use JQuery::FileUpload::Rails::Middleware
5
8
  end
6
9
  end
@@ -1,3 +1,3 @@
1
1
  module S3UpNow
2
- VERSION = "0.1.7"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3-upnow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carlos Eduardo Rodrigues Diógenes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-21 00:00:00.000000000 Z
11
+ date: 2015-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -75,12 +75,14 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - LICENSE
77
77
  - README.md
78
- - app/assets/javascripts/s3_direct_upload.js.coffee
79
- - app/assets/stylesheets/s3_direct_upload_progress_bars.css.scss
78
+ - app/assets/javascripts/s3-upnow.js.coffee
79
+ - app/assets/stylesheets/s3-upnow-progress-bar.css.scss
80
80
  - lib/s3-upnow.rb
81
81
  - lib/s3-upnow/config_aws.rb
82
82
  - lib/s3-upnow/engine.rb
83
83
  - lib/s3-upnow/form_helper.rb
84
+ - lib/s3-upnow/generator.rb
85
+ - lib/s3-upnow/paperclip.rb
84
86
  - lib/s3-upnow/railtie.rb
85
87
  - lib/s3-upnow/version.rb
86
88
  - lib/tasks/s3_upnow.rake
@@ -103,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
105
  version: '0'
104
106
  requirements: []
105
107
  rubyforge_project:
106
- rubygems_version: 2.2.2
108
+ rubygems_version: 2.4.2
107
109
  signing_key:
108
110
  specification_version: 4
109
111
  summary: Gives a form helper for Rails which allows direct uploads to s3. Based on
@@ -1,173 +0,0 @@
1
- #= require jquery-fileupload/basic
2
- #= require jquery-fileupload/vendor/tmpl
3
-
4
- $ = jQuery
5
-
6
- $.fn.S3Uploader = (options) ->
7
-
8
- # support multiple elements
9
- if @length > 1
10
- @each ->
11
- $(this).S3Uploader options
12
-
13
- return this
14
-
15
- $uploadForm = this
16
-
17
- settings =
18
- path: ''
19
- additional_data: null
20
- before_add: null
21
- remove_completed_progress_bar: true
22
- remove_failed_progress_bar: false
23
- progress_bar_target: null
24
- click_submit_target: null
25
- allow_multiple_files: true
26
-
27
- $.extend settings, options
28
-
29
- current_files = []
30
- forms_for_submit = []
31
- if settings.click_submit_target
32
- settings.click_submit_target.click ->
33
- form.submit() for form in forms_for_submit
34
- false
35
-
36
- setUploadForm = ->
37
- $uploadForm.fileupload
38
-
39
- add: (e, data) ->
40
- file = data.files[0]
41
- file.unique_id = Math.random().toString(36).substr(2,16)
42
-
43
- unless settings.before_add and not settings.before_add(file)
44
- current_files.push data
45
- if $('#template-upload').length > 0
46
- data.context = $($.trim(tmpl("template-upload", file)))
47
- $(data.context).appendTo(settings.progress_bar_target || $uploadForm)
48
- else if !settings.allow_multiple_files
49
- data.context = settings.progress_bar_target
50
- if settings.click_submit_target
51
- if settings.allow_multiple_files
52
- forms_for_submit.push data
53
- else
54
- forms_for_submit = [data]
55
- else
56
- data.submit()
57
-
58
- start: (e) ->
59
- $uploadForm.trigger("s3_uploads_start", [e])
60
-
61
- progress: (e, data) ->
62
- if data.context
63
- progress = parseInt(data.loaded / data.total * 100, 10)
64
- data.context.find('.bar').css('width', progress + '%')
65
-
66
- done: (e, data) ->
67
- content = build_content_object $uploadForm, data.files[0], data.result
68
-
69
- callback_url = $uploadForm.data('callback-url')
70
- if callback_url
71
- content[$uploadForm.data('callback-param')] = content.url
72
-
73
- $.ajax
74
- type: $uploadForm.data('callback-method')
75
- url: callback_url
76
- data: content
77
- beforeSend: ( xhr, settings ) ->
78
- event = $.Event('ajax:beforeSend')
79
- $uploadForm.trigger(event, [xhr, settings])
80
- return event.result
81
- complete: ( xhr, status ) ->
82
- event = $.Event('ajax:complete')
83
- $uploadForm.trigger(event, [xhr, status])
84
- return event.result
85
- success: ( data, status, xhr ) ->
86
- event = $.Event('ajax:success')
87
- $uploadForm.trigger(event, [data, status, xhr])
88
- return event.result
89
- error: ( xhr, status, error ) ->
90
- event = $.Event('ajax:error')
91
- $uploadForm.trigger(event, [xhr, status, error])
92
- return event.result
93
-
94
- data.context.remove() if data.context && settings.remove_completed_progress_bar # remove progress bar
95
- $uploadForm.trigger("s3_upload_complete", [content])
96
-
97
- current_files.splice($.inArray(data, current_files), 1) # remove that element from the array
98
- $uploadForm.trigger("s3_uploads_complete", [content]) unless current_files.length
99
-
100
- fail: (e, data) ->
101
- content = build_content_object $uploadForm, data.files[0], data.result
102
- content.error_thrown = data.errorThrown
103
-
104
- data.context.remove() if data.context && settings.remove_failed_progress_bar # remove progress bar
105
- $uploadForm.trigger("s3_upload_failed", [content])
106
-
107
- formData: (form) ->
108
- data = form.serializeArray()
109
- fileType = ""
110
- if "type" of @files[0]
111
- fileType = @files[0].type
112
- data.push
113
- name: "content-type"
114
- value: fileType
115
-
116
- key = $uploadForm.data("key")
117
- .replace('{timestamp}', new Date().getTime())
118
- .replace('{unique_id}', @files[0].unique_id)
119
- .replace('{extension}', @files[0].name.split('.').pop())
120
-
121
- # substitute upload timestamp and unique_id into key
122
- key_field = $.grep data, (n) ->
123
- n if n.name == "key"
124
-
125
- if key_field.length > 0
126
- key_field[0].value = settings.path + key
127
-
128
- # IE <= 9 doesn't have XHR2 hence it can't use formData
129
- # replace 'key' field to submit form
130
- unless 'FormData' of window
131
- $uploadForm.find("input[name='key']").val(settings.path + key)
132
- data
133
-
134
- build_content_object = ($uploadForm, file, result) ->
135
- content = {}
136
- if result # Use the S3 response to set the URL to avoid character encodings bugs
137
- content.url = $(result).find("Location").text()
138
- content.filepath = $('<a />').attr('href', content.url)[0].pathname
139
- else # IE <= 9 retu rn a null result object so we use the file object instead
140
- domain = $uploadForm.attr('action')
141
- content.filepath = $uploadForm.find('input[name=key]').val().replace('/${filename}', '')
142
- content.url = domain + content.filepath + '/' + encodeURIComponent(file.name)
143
-
144
- content.filename = file.name
145
- content.filesize = file.size if 'size' of file
146
- content.lastModifiedDate = file.lastModifiedDate if 'lastModifiedDate' of file
147
- content.filetype = file.type if 'type' of file
148
- content.unique_id = file.unique_id if 'unique_id' of file
149
- content.relativePath = build_relativePath(file) if has_relativePath(file)
150
- content = $.extend content, settings.additional_data if settings.additional_data
151
- content
152
-
153
- has_relativePath = (file) ->
154
- file.relativePath || file.webkitRelativePath
155
-
156
- build_relativePath = (file) ->
157
- file.relativePath || (file.webkitRelativePath.split("/")[0..-2].join("/") + "/" if file.webkitRelativePath)
158
-
159
- #public methods
160
- @initialize = ->
161
- # Save key for IE9 Fix
162
- $uploadForm.data("key", $uploadForm.find("input[name='key']").val())
163
-
164
- setUploadForm()
165
- this
166
-
167
- @path = (new_path) ->
168
- settings.path = new_path
169
-
170
- @additional_data = (new_data) ->
171
- settings.additional_data = new_data
172
-
173
- @initialize()