s3_cors_fileupload 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/CHANGELOG.md +10 -3
- data/Gemfile +11 -9
- data/Gemfile.lock +86 -65
- data/README.md +8 -4
- data/lib/generators/s3_cors_fileupload/install/install_generator.rb +5 -2
- data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads_controller.rb +3 -1
- data/lib/generators/s3_cors_fileupload/install/templates/source_file.rb +4 -3
- data/lib/generators/s3_cors_fileupload/install/templates/views/erb/_template_download.html.erb +18 -7
- data/lib/generators/s3_cors_fileupload/install/templates/views/erb/_template_upload.html.erb +4 -4
- data/lib/generators/s3_cors_fileupload/install/templates/views/erb/_template_uploaded.html.erb +17 -6
- data/lib/generators/s3_cors_fileupload/install/templates/views/erb/index.html.erb +1 -1
- data/lib/generators/s3_cors_fileupload/install/templates/views/haml/_template_download.html.haml +14 -4
- data/lib/generators/s3_cors_fileupload/install/templates/views/haml/_template_upload.html.haml +5 -5
- data/lib/generators/s3_cors_fileupload/install/templates/views/haml/_template_uploaded.html.haml +12 -1
- data/lib/generators/s3_cors_fileupload/install/templates/views/haml/index.html.haml +1 -1
- data/lib/s3_cors_fileupload.rb +6 -0
- data/lib/s3_cors_fileupload/rails.rb +1 -1
- data/lib/s3_cors_fileupload/rails/form_helper.rb +15 -12
- data/lib/s3_cors_fileupload/version.rb +3 -3
- data/s3_cors_fileupload.gemspec +3 -4
- data/spec/dummy/Rakefile +0 -1
- data/spec/dummy/app/assets/javascripts/application.js +4 -3
- data/spec/dummy/app/assets/javascripts/s3_uploads.js +92 -0
- data/spec/dummy/app/assets/stylesheets/application.css +1 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -1
- data/spec/dummy/app/controllers/s3_uploads_controller.rb +56 -0
- data/spec/dummy/app/models/source_file.rb +54 -0
- data/spec/dummy/app/views/layouts/application.html.erb +2 -2
- data/spec/dummy/app/views/s3_uploads/_template_download.html.erb +43 -0
- data/spec/dummy/app/views/s3_uploads/_template_upload.html.erb +36 -0
- data/spec/dummy/app/views/s3_uploads/_template_uploaded.html.erb +41 -0
- data/spec/dummy/app/views/s3_uploads/index.html.erb +41 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +1 -1
- data/spec/dummy/config/application.rb +2 -33
- data/spec/dummy/config/boot.rb +4 -9
- data/spec/dummy/config/environment.rb +2 -2
- data/spec/dummy/config/environments/development.rb +14 -19
- data/spec/dummy/config/environments/production.rb +40 -27
- data/spec/dummy/config/environments/test.rb +14 -12
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +6 -5
- data/spec/dummy/config/initializers/secret_token.rb +7 -2
- data/spec/dummy/config/initializers/session_store.rb +0 -5
- data/spec/dummy/config/initializers/wrap_parameters.rb +6 -6
- data/spec/dummy/config/locales/en.yml +20 -2
- data/spec/dummy/config/routes.rb +27 -24
- data/spec/dummy/db/migrate/20131001201535_create_source_files.rb +14 -0
- data/spec/dummy/db/schema.rb +27 -0
- data/spec/dummy/public/404.html +43 -11
- data/spec/dummy/public/422.html +43 -11
- data/spec/dummy/public/500.html +43 -11
- data/spec/features/uploads_spec.rb +37 -0
- data/spec/lib/s3_cors_fileupload/rails/engine_spec.rb +8 -0
- data/spec/lib/s3_cors_fileupload/rails/form_helper_spec.rb +30 -0
- data/spec/lib/s3_cors_fileupload/rails/policy_helper_spec.rb +95 -0
- data/spec/s3_cors_fileupload_spec.rb +8 -4
- data/spec/spec_helper.rb +8 -8
- data/spec/support/dummy.pdf +0 -0
- data/vendor/assets/javascripts/s3_cors_fileupload/index.js +1 -0
- data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload-image.js +111 -32
- data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload-ui.js +24 -18
- data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload-validate.js +7 -6
- data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload.js +22 -15
- data/vendor/assets/javascripts/s3_cors_fileupload/vendor/load-image-meta.js +137 -0
- data/vendor/assets/javascripts/s3_cors_fileupload/vendor/tmpl.js +8 -8
- data/vendor/assets/stylesheets/jquery.fileupload-ui.css.erb +2 -1
- metadata +56 -28
- data/spec/dummy/script/rails +0 -6
data/lib/generators/s3_cors_fileupload/install/templates/views/haml/_template_download.html.haml
CHANGED
|
@@ -7,21 +7,31 @@
|
|
|
7
7
|
%span.preview
|
|
8
8
|
{% if (file.thumbnailUrl) { %}
|
|
9
9
|
%a{:download => "{%=file.name%}", :href => "{%=file.url%}", :title => "{%=file.name%}", :"data-gallery" => ''}
|
|
10
|
-
%img{:src => "{%=file.thumbnailUrl%}"}
|
|
10
|
+
%img{:src => "{%=file.thumbnailUrl%}"}
|
|
11
11
|
{% } %}
|
|
12
12
|
%td
|
|
13
13
|
%p.name
|
|
14
|
+
{% if (file.url) { %}
|
|
14
15
|
%a{:href => "{%=file.url%}", :title => "{%=file.name%}", :download => "{%=file.name%}", :"data-gallery" => !"{%= file.thumbnailUrl ? ' ' : '' %}".html_safe.empty? && ''} {%=file.name%}
|
|
16
|
+
{% } else { %}
|
|
17
|
+
%span {%=file.name%}
|
|
18
|
+
{% } %}
|
|
15
19
|
{% if (file.error) { %}
|
|
16
20
|
%div
|
|
17
|
-
%span.label.label-
|
|
21
|
+
%span.label.label-danger Error
|
|
18
22
|
{%=file.error%}
|
|
19
23
|
{% } %}
|
|
20
24
|
%td
|
|
21
25
|
%span.size {%=o.formatFileSize(file.size)%}
|
|
22
26
|
%td
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
{% if (file.deleteUrl) { %}
|
|
28
|
+
%button.btn.btn-danger.delete{"data-type" => "{%=file.deleteType%}", "data-url" => "{%=file.deleteUrl%}", "data-confirmation" => "Are you sure?", "data-xhr-fields" => !"{% if (file.delete_with_credentials) { %} {'withCredentials': true} {% } %}".blank? && "{% if (file.delete_with_credentials) { %} {'withCredentials': true} {% } %}"}
|
|
29
|
+
%i.glyphicon.glyphicon-trash
|
|
25
30
|
%span Delete
|
|
26
31
|
%input.toggle{:name => "delete", :type => "checkbox", :value => "1"}
|
|
32
|
+
{% } else { %}
|
|
33
|
+
%button.btn.btn-warning.cancel
|
|
34
|
+
%i.glyphicon.glyphicon-ban-circle
|
|
35
|
+
%span Cancel
|
|
36
|
+
{% } %}
|
|
27
37
|
{% } %}
|
data/lib/generators/s3_cors_fileupload/install/templates/views/haml/_template_upload.html.haml
CHANGED
|
@@ -9,24 +9,24 @@
|
|
|
9
9
|
%p.name {%=file.name%}
|
|
10
10
|
{% if (file.error) { %}
|
|
11
11
|
%div
|
|
12
|
-
%span.label.label-
|
|
12
|
+
%span.label.label-danger Error
|
|
13
13
|
{%=file.error%}
|
|
14
14
|
{% } %}
|
|
15
15
|
%td
|
|
16
16
|
%p.size {%=o.formatFileSize(file.size)%}
|
|
17
17
|
{% if (!o.files.error) { %}
|
|
18
|
-
.progress.progress-
|
|
19
|
-
.bar{:style => "width:0%;"}
|
|
18
|
+
.progress.progress-striped.active{:role => 'progressbar', :"aria-valuemin" => '0', :"aria-valuemax" => '100', :"aria-valuenow" => '0'}
|
|
19
|
+
.progress-bar.progress-bar-success{:style => "width:0%;"}
|
|
20
20
|
{% } %}
|
|
21
21
|
%td
|
|
22
22
|
{% if (!o.files.error && !i && !o.options.autoUpload) { %}
|
|
23
23
|
%button.btn.btn-primary.start
|
|
24
|
-
%i.
|
|
24
|
+
%i.glyphicon.glyphicon-upload
|
|
25
25
|
%span Start
|
|
26
26
|
{% } %}
|
|
27
27
|
{% if (!i) { %}
|
|
28
28
|
%button.btn.btn-warning.cancel
|
|
29
|
-
%i.
|
|
29
|
+
%i.glyphicon.glyphicon-ban-circle
|
|
30
30
|
%span Cancel
|
|
31
31
|
{% } %}
|
|
32
32
|
{% } %}
|
data/lib/generators/s3_cors_fileupload/install/templates/views/haml/_template_uploaded.html.haml
CHANGED
|
@@ -10,11 +10,22 @@
|
|
|
10
10
|
{% } %}
|
|
11
11
|
%td
|
|
12
12
|
%p.name
|
|
13
|
-
%
|
|
13
|
+
{% if (o.url) { %}
|
|
14
|
+
%a{:href => "{%=o.url%}", :title => "{%=o.name%}", :download => "{%=o.name%}", :"data-gallery" => !"{%= o.image ? 'true' : '' %}".html_safe.empty? && ''} {%=o.name%}
|
|
15
|
+
{% } else { %}
|
|
16
|
+
%span {%=o.name%}
|
|
17
|
+
{% } %}
|
|
14
18
|
%td
|
|
15
19
|
%span.size {%=formatFileSize(o.size)%}
|
|
16
20
|
%td
|
|
21
|
+
{% if (o.delete_url) { %}
|
|
17
22
|
%button.btn.btn-danger.delete{"data-type" => "DELETE", "data-url" => "{%=o.delete_url%}", "data-object_id" => "{%=o.id%}", "data-confirmation" => "Are you sure?", "data-xhr-fields" => !"{% if (o.delete_with_credentials) { %} {'withCredentials': true} {% } %}".blank? && "{% if (o.delete_with_credentials) { %} {'withCredentials': true} {% } %}"}
|
|
18
23
|
%i.icon-trash.icon-white
|
|
19
24
|
%span Delete
|
|
20
25
|
%input.toggle{:name => "delete", :type => "checkbox", :value => "1"}
|
|
26
|
+
{% } else { %}
|
|
27
|
+
%button.btn.btn-warning.cancel
|
|
28
|
+
%i.glyphicon.glyphicon-ban-circle
|
|
29
|
+
%span Cancel
|
|
30
|
+
{% } %}
|
|
31
|
+
|
data/lib/s3_cors_fileupload.rb
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
require 's3_cors_fileupload/version'
|
|
2
2
|
require 's3_cors_fileupload/rails'
|
|
3
|
+
|
|
4
|
+
module S3CorsFileupload
|
|
5
|
+
def self.active_record_protected_attributes?
|
|
6
|
+
@active_record_protected_attributes ||= ActiveRecord::VERSION::STRING.to_f < 4.0 || !!defined?(ProtectedAttributes)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
if defined?(::Rails)
|
|
2
2
|
require 's3_cors_fileupload/rails/config'
|
|
3
|
-
require 's3_cors_fileupload/rails/engine' if ::Rails
|
|
3
|
+
require 's3_cors_fileupload/rails/engine' if defined? ::Rails::Engine
|
|
4
4
|
require 's3_cors_fileupload/rails/policy_helper'
|
|
5
5
|
require 's3_cors_fileupload/rails/form_helper'
|
|
6
6
|
|
|
@@ -14,6 +14,9 @@ module S3CorsFileupload
|
|
|
14
14
|
# :bucket The name of the bucket on S3 you wish for the files to be uploaded to.
|
|
15
15
|
# Defaults to `Config.bucket` (read from the yaml config file).
|
|
16
16
|
#
|
|
17
|
+
# :secure Dictates whether the form action URL will be pointing to a secure URL or not.
|
|
18
|
+
# Defaults to `true`.
|
|
19
|
+
#
|
|
17
20
|
# Any other key creates standard HTML options for the form tag.
|
|
18
21
|
def s3_cors_fileupload_form_tag(options = {}, &block)
|
|
19
22
|
policy_helper = PolicyHelper.new(options)
|
|
@@ -28,9 +31,9 @@ module S3CorsFileupload
|
|
|
28
31
|
:success_action_status => '201'
|
|
29
32
|
}
|
|
30
33
|
# assume that all of the non-documented keys are
|
|
31
|
-
_html_options = options.reject { |key, val| [:access_key_id, :acl, :max_file_size, :bucket].include?(key) }
|
|
34
|
+
_html_options = options.reject { |key, val| [:access_key_id, :acl, :max_file_size, :bucket, :secure].include?(key) }
|
|
32
35
|
# return the form html
|
|
33
|
-
construct_form_html(hidden_form_fields, policy_helper.options[:bucket], _html_options, &block)
|
|
36
|
+
construct_form_html(hidden_form_fields, policy_helper.options[:bucket], options[:secure], _html_options, &block)
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
alias_method :s3_cors_fileupload_form, :s3_cors_fileupload_form_tag
|
|
@@ -42,31 +45,31 @@ module S3CorsFileupload
|
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
# hidden fields argument should be a hash of key value pairs (values may be blank if desired)
|
|
45
|
-
def construct_form_html(hidden_fields, bucket, html_options = {}, &block)
|
|
48
|
+
def construct_form_html(hidden_fields, bucket, secure = true, html_options = {}, &block)
|
|
46
49
|
# now build the html for the form
|
|
47
|
-
form_tag("https://#{bucket}.s3.amazonaws.com", build_form_options(html_options)) do
|
|
50
|
+
form_tag(secure == false ? "http://#{bucket}.s3.amazonaws.com" : "https://#{bucket}.s3.amazonaws.com", build_form_options(html_options)) do
|
|
48
51
|
hidden_fields.map do |name, value|
|
|
49
52
|
hidden_field_tag(name, value)
|
|
50
53
|
end.join.html_safe + "
|
|
51
54
|
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
|
|
52
55
|
<div class='row fileupload-buttonbar'>
|
|
53
|
-
<div class='
|
|
56
|
+
<div class='col-lg-7'>
|
|
54
57
|
<span class='btn btn-success fileinput-button'>
|
|
55
|
-
<i class='
|
|
58
|
+
<i class='glyphicon glyphicon-plus'></i>
|
|
56
59
|
<span>Add files...</span>
|
|
57
60
|
".html_safe +
|
|
58
61
|
file_field_tag(:file, :multiple => true) + "
|
|
59
62
|
</span>
|
|
60
63
|
<button type='submit' class='btn btn-primary start'>
|
|
61
|
-
<i class='
|
|
64
|
+
<i class='glyphicon glyphicon-upload'></i>
|
|
62
65
|
<span>Start upload</span>
|
|
63
66
|
</button>
|
|
64
67
|
<button type='reset' class='btn btn-warning cancel'>
|
|
65
|
-
<i class='
|
|
68
|
+
<i class='glyphicon glyphicon-ban-circle'></i>
|
|
66
69
|
<span>Cancel upload</span>
|
|
67
70
|
</button>
|
|
68
71
|
<button type='button' class='btn btn-danger delete'>
|
|
69
|
-
<i class='
|
|
72
|
+
<i class='glyphicon glyphicon-trash'></i>
|
|
70
73
|
<span>Delete</span>
|
|
71
74
|
</button>
|
|
72
75
|
<input type='checkbox' class='toggle'></input>
|
|
@@ -74,10 +77,10 @@ module S3CorsFileupload
|
|
|
74
77
|
<span class='fileupload-loading'></span>
|
|
75
78
|
</div>
|
|
76
79
|
<!-- The global progress information -->
|
|
77
|
-
<div class='
|
|
80
|
+
<div class='col-lg-5 fileupload-progress fade'>
|
|
78
81
|
<!-- The global progress bar -->
|
|
79
|
-
<div class='progress progress-
|
|
80
|
-
<div class='bar' style='width: 0%;'></div>
|
|
82
|
+
<div class='progress progress-striped active' role='progressbar' aria-valuemin='0' aria-valuemax='100'>
|
|
83
|
+
<div class='progress-bar progress-bar-success' style='width: 0%;'></div>
|
|
81
84
|
</div>
|
|
82
85
|
<!-- The extended global progress information -->
|
|
83
86
|
<div class='progress-extended'> </div>
|
data/s3_cors_fileupload.gemspec
CHANGED
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
|
6
6
|
s.version = S3CorsFileupload::VERSION
|
|
7
7
|
s.platform = Gem::Platform::RUBY
|
|
8
8
|
s.authors = ["Ben Atkins"]
|
|
9
|
-
s.email = ["
|
|
9
|
+
s.email = ["batkinz@gmail.com"]
|
|
10
10
|
s.homepage = "http://github.com/fullbridge-batkins/s3_cors_fileupload"
|
|
11
11
|
s.summary = "File uploads for Rails ~> 3.1 to AWS-S3 via CORS using the jQuery-File-Upload script"
|
|
12
12
|
s.description = "Provides file uploads for Rails ~> 3.1 to AWS-S3 via CORS using the jQuery-File-Upload javascript"
|
|
@@ -23,10 +23,9 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
s.extra_rdoc_files = %w(README.md CHANGELOG.md LICENSE.txt)
|
|
24
24
|
s.rdoc_options = %w(--charset=UTF-8)
|
|
25
25
|
|
|
26
|
-
s.add_dependency('rails', ['
|
|
26
|
+
s.add_dependency('rails', ['>= 3.1', '< 5.0'])
|
|
27
27
|
s.add_dependency('multi_json', ['~> 1.0'])
|
|
28
|
-
s.add_dependency('
|
|
29
|
-
s.add_dependency('aws-s3', ['~> 0.6']) # :require => 'aws/s3'
|
|
28
|
+
s.add_dependency('aws-s3', ['~> 0.6'])
|
|
30
29
|
|
|
31
30
|
s.add_development_dependency('rake', ['>= 0.8.7'])
|
|
32
31
|
s.add_development_dependency('bundler', ['>= 0'])
|
data/spec/dummy/Rakefile
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
|
6
6
|
//
|
|
7
7
|
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
|
8
|
-
//
|
|
8
|
+
// compiled file.
|
|
9
9
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
|
11
|
+
// about supported directives.
|
|
12
12
|
//
|
|
13
13
|
//= require jquery
|
|
14
14
|
//= require jquery_ujs
|
|
15
|
+
//= require s3_cors_fileupload
|
|
15
16
|
//= require_tree .
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* s3-cors-file-upload
|
|
3
|
+
* http://github.com/fullbridge-batkins/s3_cors_fileupload
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2013, Ben Atkins
|
|
6
|
+
* http://batkins.net
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the MIT license:
|
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// This global variable will hold s3 file credentials for files until it's time to submit them
|
|
13
|
+
var s3_upload_hash = {};
|
|
14
|
+
|
|
15
|
+
$(function() {
|
|
16
|
+
// hit the controller for info when the file comes in
|
|
17
|
+
$('#fileupload').bind('fileuploadadd', function (e, data) {
|
|
18
|
+
var content_type = data.files[0].type;
|
|
19
|
+
var file_name = data.files[0].name;
|
|
20
|
+
|
|
21
|
+
$.getJSON('/source_files/generate_key.json', {filename: file_name}, function(data) {
|
|
22
|
+
// Now that we have our data, we add it to the global s3_upload_hash so that it can be
|
|
23
|
+
// accessed (in the fileuploadsubmit callback) prior to being submitted
|
|
24
|
+
s3_upload_hash[file_name] = {
|
|
25
|
+
key: data.key,
|
|
26
|
+
content_type: content_type
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// this gets triggered right before a file is about to be sent (and have their form action submitted)
|
|
32
|
+
$('#fileupload').bind('fileuploadsubmit', function (e, data) {
|
|
33
|
+
var file_name = data.files[0].name;
|
|
34
|
+
// transfer the data from the upload-template .form hidden fields to the real form's hidden fields
|
|
35
|
+
var form = $('#fileupload');
|
|
36
|
+
form.find('input[name=key]').val(s3_upload_hash[file_name]['key']);
|
|
37
|
+
form.find('input[name=Content-Type]').val(s3_upload_hash[file_name]['content_type']);
|
|
38
|
+
delete s3_upload_hash[file_name];
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
$('#fileupload').bind('fileuploaddone', function (e, data) {
|
|
42
|
+
// the response will be XML, and can be accessed by calling `data.result`
|
|
43
|
+
//
|
|
44
|
+
// Here is an example of what the XML will look like coming back from S3:
|
|
45
|
+
// <PostResponse>
|
|
46
|
+
// <Location>https://bucket-name.s3.amazonaws.com/uploads%2F3ducks.jpg</Location>
|
|
47
|
+
// <Bucket>bucket-name</Bucket>
|
|
48
|
+
// <Key>uploads/3ducks.jpg</Key>
|
|
49
|
+
// <ETag>"c7902ef289687931f34f92b65afda320"</ETag>
|
|
50
|
+
// </PostResponse>
|
|
51
|
+
|
|
52
|
+
$.post('/source_files.json',
|
|
53
|
+
{
|
|
54
|
+
'source_file[url]': $(data.result).find('Location').text(),
|
|
55
|
+
'source_file[bucket]': $(data.result).find('Bucket').text(),
|
|
56
|
+
'source_file[key]': $(data.result).find('Key').text(),
|
|
57
|
+
authenticity_token: $('meta[name=csrf-token]').attr('content')
|
|
58
|
+
},
|
|
59
|
+
function(data) {
|
|
60
|
+
$('#upload_files tbody').append(tmpl('template-uploaded', data));
|
|
61
|
+
},
|
|
62
|
+
'json'
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
$('#fileupload').bind('fileuploadcompleted', function (e, data) {
|
|
67
|
+
// remove the downloaded templates, since in the above function we put our own custom 'template-uploaded' onto the list instead
|
|
68
|
+
data.context.remove();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
$('#fileupload').bind('fileuploaddestroyed', function (e, data) {
|
|
72
|
+
if (!data.url) // sometimes this callback seems to get triggered a couple times, and has null data after the first time
|
|
73
|
+
return null;
|
|
74
|
+
|
|
75
|
+
// remove the table row containing the source file information from the page
|
|
76
|
+
$('#source_file_' + data.object_id).remove();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// used for displaying approximate file size on the file listing index.
|
|
82
|
+
// functionality mimics what the jQuery-File-Upload script does.
|
|
83
|
+
function formatFileSize(bytes) {
|
|
84
|
+
if (typeof bytes !== 'number')
|
|
85
|
+
return '';
|
|
86
|
+
else if (bytes >= 1000000000)
|
|
87
|
+
return (bytes / 1000000000).toFixed(2) + ' GB';
|
|
88
|
+
else if (bytes >= 1000000)
|
|
89
|
+
return (bytes / 1000000).toFixed(2) + ' MB';
|
|
90
|
+
else
|
|
91
|
+
return (bytes / 1000).toFixed(2) + ' KB';
|
|
92
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class S3UploadsController < ApplicationController
|
|
2
|
+
# GET /source_files
|
|
3
|
+
# GET /source_files.json
|
|
4
|
+
def index
|
|
5
|
+
@source_files = SourceFile.all
|
|
6
|
+
|
|
7
|
+
respond_to do |format|
|
|
8
|
+
format.html # index.html.erb
|
|
9
|
+
format.json { render json: @source_files.map(&:to_jq_upload) }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# POST /source_files
|
|
14
|
+
# POST /source_files.json
|
|
15
|
+
def create
|
|
16
|
+
# this line allows for compatibility with `ProtectedAttributes` or `StrongParameters`
|
|
17
|
+
parameters = S3CorsFileupload.active_record_protected_attributes? ? params[:source_file] : params.require(:source_file).permit(:url, :bucket, :key)
|
|
18
|
+
@source_file = SourceFile.new(parameters)
|
|
19
|
+
respond_to do |format|
|
|
20
|
+
if @source_file.save
|
|
21
|
+
format.html {
|
|
22
|
+
render :json => @source_file.to_jq_upload,
|
|
23
|
+
:content_type => 'text/html',
|
|
24
|
+
:layout => false
|
|
25
|
+
}
|
|
26
|
+
format.json { render json: @source_file.to_jq_upload, status: :created }
|
|
27
|
+
else
|
|
28
|
+
format.html { render action: "new" }
|
|
29
|
+
format.json { render json: @source_file.errors, status: :unprocessable_entity }
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# DELETE /source_files/1
|
|
35
|
+
# DELETE /source_files/1.json
|
|
36
|
+
def destroy
|
|
37
|
+
@source_file = SourceFile.find(params[:id])
|
|
38
|
+
@source_file.destroy
|
|
39
|
+
|
|
40
|
+
respond_to do |format|
|
|
41
|
+
format.html { redirect_to source_files_url }
|
|
42
|
+
format.json { head :no_content }
|
|
43
|
+
format.xml { head :no_content }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# used for s3_uploader
|
|
48
|
+
def generate_key
|
|
49
|
+
uid = SecureRandom.uuid.gsub(/-/,'')
|
|
50
|
+
|
|
51
|
+
render json: {
|
|
52
|
+
key: "uploads/#{uid}/#{params[:filename]}",
|
|
53
|
+
success_action_redirect: "/"
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'aws/s3'
|
|
2
|
+
|
|
3
|
+
class SourceFile < ActiveRecord::Base
|
|
4
|
+
# This line can be removed for Rails 4 apps that are using Strong Parameters
|
|
5
|
+
attr_accessible :url, :bucket, :key if S3CorsFileupload.active_record_protected_attributes?
|
|
6
|
+
|
|
7
|
+
validates_presence_of :file_name, :file_content_type, :file_size, :key, :bucket
|
|
8
|
+
|
|
9
|
+
before_validation(:on => :create) do
|
|
10
|
+
self.file_name = key.split('/').last if key
|
|
11
|
+
# for some reason, the response from AWS seems to escape the slashes in the keys, this line will unescape the slash
|
|
12
|
+
self.url = url.gsub(/%2F/, '/') if url
|
|
13
|
+
self.file_size ||= s3_object.size rescue nil
|
|
14
|
+
self.file_content_type ||= s3_object.content_type rescue nil
|
|
15
|
+
end
|
|
16
|
+
# make all attributes readonly after creating the record (not sure we need this?)
|
|
17
|
+
after_create { readonly! }
|
|
18
|
+
# cleanup; destroy corresponding file on S3
|
|
19
|
+
after_destroy { s3_object.try(:delete) }
|
|
20
|
+
|
|
21
|
+
def to_jq_upload
|
|
22
|
+
{
|
|
23
|
+
'id' => id,
|
|
24
|
+
'name' => file_name,
|
|
25
|
+
'size' => file_size,
|
|
26
|
+
'url' => url,
|
|
27
|
+
'image' => self.is_image?,
|
|
28
|
+
'delete_url' => Rails.application.routes.url_helpers.source_file_path(self, :format => :json)
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def is_image?
|
|
33
|
+
!!file_content_type.try(:match, /image/)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#---- start S3 related methods -----
|
|
37
|
+
def s3_object
|
|
38
|
+
@s3_object ||= AWS::S3::S3Object.find(key, bucket) if self.class.open_aws && key
|
|
39
|
+
rescue
|
|
40
|
+
nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.open_aws
|
|
44
|
+
unless @aws_connected
|
|
45
|
+
AWS::S3::Base.establish_connection!(
|
|
46
|
+
:access_key_id => S3CorsFileupload::Config.access_key_id,
|
|
47
|
+
:secret_access_key => S3CorsFileupload::Config.secret_access_key
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
@aws_connected ||= AWS::S3::Base.connected?
|
|
51
|
+
end
|
|
52
|
+
#---- end S3 related methods -----
|
|
53
|
+
|
|
54
|
+
end
|