s3_cors_fileupload 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.document +5 -0
  2. data/.gitignore +51 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +14 -0
  5. data/Gemfile.lock +39 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +104 -0
  8. data/Rakefile +58 -0
  9. data/lib/generators/s3_cors_fileupload/install/USAGE +17 -0
  10. data/lib/generators/s3_cors_fileupload/install/install_generator.rb +51 -0
  11. data/lib/generators/s3_cors_fileupload/install/templates/amazon_s3.yml +17 -0
  12. data/lib/generators/s3_cors_fileupload/install/templates/create_source_files.rb +14 -0
  13. data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads.js +94 -0
  14. data/lib/generators/s3_cors_fileupload/install/templates/s3_uploads_controller.rb +90 -0
  15. data/lib/generators/s3_cors_fileupload/install/templates/source_file.rb +53 -0
  16. data/lib/generators/s3_cors_fileupload/install/templates/views/_template_download.html.erb +29 -0
  17. data/lib/generators/s3_cors_fileupload/install/templates/views/_template_upload.html.erb +31 -0
  18. data/lib/generators/s3_cors_fileupload/install/templates/views/_template_uploaded.html.erb +25 -0
  19. data/lib/generators/s3_cors_fileupload/install/templates/views/index.html.erb +43 -0
  20. data/lib/s3_cors_fileupload.rb +2 -0
  21. data/lib/s3_cors_fileupload/rails.rb +8 -0
  22. data/lib/s3_cors_fileupload/rails/config.rb +27 -0
  23. data/lib/s3_cors_fileupload/rails/engine.rb +6 -0
  24. data/lib/s3_cors_fileupload/rails/form_helper.rb +91 -0
  25. data/lib/s3_cors_fileupload/rails/policy_helper.rb +48 -0
  26. data/lib/s3_cors_fileupload/version.rb +5 -0
  27. data/s3_cors_fileupload.gemspec +35 -0
  28. data/spec/s3_cors_fileupload/version_spec.rb +17 -0
  29. data/spec/s3_cors_fileupload_spec.rb +9 -0
  30. data/spec/spec_helper.rb +16 -0
  31. data/vendor/assets/images/loading.gif +0 -0
  32. data/vendor/assets/images/progressbar.gif +0 -0
  33. data/vendor/assets/javascripts/s3_cors_fileupload/index.js +6 -0
  34. data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload-ui.js +732 -0
  35. data/vendor/assets/javascripts/s3_cors_fileupload/jquery.fileupload.js +1106 -0
  36. data/vendor/assets/javascripts/s3_cors_fileupload/jquery.iframe-transport.js +172 -0
  37. data/vendor/assets/javascripts/s3_cors_fileupload/vendor/jquery.ui.widget.js +511 -0
  38. data/vendor/assets/javascripts/s3_cors_fileupload/vendor/load-image.js +122 -0
  39. data/vendor/assets/javascripts/s3_cors_fileupload/vendor/tmpl.js +87 -0
  40. data/vendor/assets/stylesheets/jquery.fileupload-ui.css.erb +85 -0
  41. metadata +205 -0
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
@@ -0,0 +1,51 @@
1
+ .rvmrc
2
+
3
+ # rcov generated
4
+ coverage
5
+ coverage.data
6
+
7
+ # rdoc generated
8
+ rdoc
9
+
10
+ # yard generated
11
+ doc
12
+ .yardoc
13
+
14
+ # bundler
15
+ .bundle
16
+
17
+ # jeweler generated
18
+ pkg
19
+
20
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
21
+ #
22
+ # * Create a file at ~/.gitignore
23
+ # * Include files you want ignored
24
+ # * Run: git config --global core.excludesfile ~/.gitignore
25
+ #
26
+ # After doing this, these files will be ignored in all your git projects,
27
+ # saving you from having to 'pollute' every project you touch with them
28
+ #
29
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
30
+ #
31
+ # For MacOS:
32
+ #
33
+ #.DS_Store
34
+
35
+ # For TextMate
36
+ #*.tmproj
37
+ #tmtags
38
+
39
+ # For emacs:
40
+ #*~
41
+ #\#*
42
+ #.\#*
43
+
44
+ # For vim:
45
+ #*.swp
46
+
47
+ # For redcar:
48
+ #.redcar
49
+
50
+ # For rubinius:
51
+ #*.rbc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source :rubygems
2
+
3
+ # Add dependencies to develop your gem here.
4
+ # Include everything needed to run rake, tests, features, etc.
5
+ group :development do
6
+ gem 'bundler'
7
+ gem 'rdoc', '~> 3.12'
8
+ gem 'jeweler', '~> 1.8.4'
9
+ end
10
+
11
+ group :test do
12
+ gem 'rspec', '~> 2.11'
13
+ gem 'shoulda-matchers'
14
+ end
@@ -0,0 +1,39 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.8)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ diff-lcs (1.1.3)
8
+ git (1.2.5)
9
+ i18n (0.6.1)
10
+ jeweler (1.8.4)
11
+ bundler (~> 1.0)
12
+ git (>= 1.2.5)
13
+ rake
14
+ rdoc
15
+ json (1.7.5)
16
+ multi_json (1.3.6)
17
+ rake (0.9.2.2)
18
+ rdoc (3.12)
19
+ json (~> 1.4)
20
+ rspec (2.11.0)
21
+ rspec-core (~> 2.11.0)
22
+ rspec-expectations (~> 2.11.0)
23
+ rspec-mocks (~> 2.11.0)
24
+ rspec-core (2.11.1)
25
+ rspec-expectations (2.11.3)
26
+ diff-lcs (~> 1.1.3)
27
+ rspec-mocks (2.11.3)
28
+ shoulda-matchers (1.4.1)
29
+ activesupport (>= 3.0.0)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ bundler
36
+ jeweler (~> 1.8.4)
37
+ rdoc (~> 3.12)
38
+ rspec (~> 2.11)
39
+ shoulda-matchers
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Ben Atkins
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,104 @@
1
+ # S3CorsFileupload
2
+
3
+ A gem to allow for uploading of files to directly AWS-S3 via CORS via the
4
+ [jQuery-File-Upload javascript](http://blueimp.github.com/jQuery-File-Upload/) for Rails 3.1 and greater.
5
+
6
+ ## Installation
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 's3_cors_fileupload'
10
+
11
+ Then run `bundle install`.
12
+
13
+ Next run the install generator, which creates a config file, then generates (but does not run)
14
+ a migration to add a source_files table and a corresponding model, as well as a controller, routes,
15
+ and views for the file uploading.
16
+
17
+ bundle exec rails generate s3_cors_fileupload:install
18
+
19
+ Now run the migration that was just generated:
20
+
21
+ bundle exec rake db:migrate
22
+
23
+ As you may have noticed, a config file was generated at `config/amazon_s3.yml`. Edit this file and fill in
24
+ the fields with your AWS S3 credentials. You can make the config load from environment variables if you wish
25
+ not to commit your S3 account information to your repository, like so:
26
+
27
+ secret_access_key: <%= ENV['S3_SECRET_ACCESS_KEY'] %>
28
+
29
+ Add the following javascript and CSS to your asset pipeline:
30
+
31
+ **s3_cors_fileupload.js**
32
+ ```javascript
33
+ //= require s3_cors_fileupload
34
+ ```
35
+
36
+ **jquery.fileupload-ui.css**
37
+ ```css
38
+ *= require jquery.fileupload-ui
39
+ ```
40
+
41
+ Now before you're ready to run the application, make sure your AWS S3 CORS settings for your bucket are setup
42
+ to receive file uploads. Before you put the application into production, I would highly recommend reading
43
+ [the official documentation for CORS](http://docs.amazonwebservices.com/AmazonS3/latest/dev/cors.html).
44
+ If you just want to get up and running, here is a configuration that will get you going:
45
+
46
+ ```
47
+ <CORSConfiguration>
48
+ <CORSRule>
49
+ <AllowedOrigin>http://localhost:3000</AllowedOrigin>
50
+ <AllowedMethod>GET</AllowedMethod>
51
+ <AllowedMethod>POST</AllowedMethod>
52
+ <AllowedMethod>PUT</AllowedMethod>
53
+ <MaxAgeSeconds>3000</MaxAgeSeconds>
54
+ <AllowedHeader>*</AllowedHeader>
55
+ </CORSRule>
56
+ </CORSConfiguration>
57
+ ```
58
+
59
+ If you use this CORS Config, and you start to see warnings like
60
+ "Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin", then you can modify the `AllowedOrigin`
61
+ line like so:
62
+
63
+ <AllowedOrigin>*</AllowedOrigin>
64
+
65
+ Just be sure to change this before you put it into production, otherwise anybody can upload to your bucket from any domain.
66
+
67
+ ## Usage
68
+
69
+ Run your rails server
70
+
71
+ bundle exec rails s
72
+
73
+ Then navigate to `http://<server_root>/source_files` to get started. The files that `s3_cors_fileupload`'s install generator
74
+ provide you with are just a guide to get you started. I thought this would be helpful to others since it took me a while to
75
+ get the [jQuery-File-Upload javascript](http://blueimp.github.com/jQuery-File-Upload/) uploading directly to S3. I encourage
76
+ you to modify the controller, source files, and javascript as you see fit!
77
+
78
+ ## Notes
79
+
80
+ The UI version of the [jQuery-File-Upload javascript](http://blueimp.github.com/jQuery-File-Upload/)
81
+ javascript uses aspects of [Twitter's Bootstrap](http://twitter.github.com/bootstrap/) for styling purposes.
82
+ In index view file from this gem's generator it is included via a `stylesheet_link_tag` to use a copy of it
83
+ [BootstrapCDN](http://www.bootstrapcdn.com/), but if you plan to use bootstrap in more places throughout
84
+ your application, you may want look into using a gem such as
85
+ `[twitter-bootstrap-rails](https://github.com/seyhunak/twitter-bootstrap-rails)`, which allows you to inject
86
+ the stylesheets and javascripts from bootstrap into the asset pipeline.
87
+
88
+ ## Contributing to S3CorsFileupload
89
+
90
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
91
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
92
+ * Fork the project.
93
+ * Start a feature/bugfix branch.
94
+ * Commit and push until you are happy with your contribution.
95
+ * Please try to add tests. This is important so I don't break it in a future version unintentionally.
96
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
97
+ * Make a pull request.
98
+
99
+ Note: I am still in the process of trying to write a more thorough test suite, so any specs people want to contribute would be very welcome!
100
+
101
+ ## Copyright
102
+
103
+ Copyright (c) 2012 Ben Atkins. See [LICENSE.txt](https://github.com/fullbridge-batkins/s3_cors_fileupload/blob/master/LICENSE.txt)
104
+ for further details.
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
10
+ gem.name = "s3_cors_fileupload"
11
+ gem.homepage = "http://github.com/fullbridge-batkins/s3_cors_fileupload"
12
+ gem.license = "MIT"
13
+ gem.summary = %q{File uploads for Rails ~> 3.1 to AWS-S3 via CORS using the jQuery-File-Upload javascript}
14
+ gem.description = %q{File uploads for Rails ~> 3.1 to AWS-S3 via CORS using the jQuery-File-Upload javascript}
15
+ gem.email = ["benatkins@fullbridge.com"]
16
+ gem.authors = ["Ben Atkins"]
17
+ # dependencies defined in Gemfile
18
+ end
19
+ Jeweler::RubygemsDotOrgTasks.new
20
+
21
+ require 'rspec/core/rake_task'
22
+ RSpec::Core::RakeTask.new('spec')
23
+
24
+ # If you want to make this the default task
25
+ task :default => :spec
26
+
27
+ # require 'rake/testtask'
28
+ # Rake::TestTask.new(:test) do |test|
29
+ # test.libs << 'lib' << 'test'
30
+ # test.pattern = 'test/**/test_*.rb'
31
+ # test.verbose = true
32
+ # end
33
+ #
34
+ # require 'rcov/rcovtask'
35
+ # Rcov::RcovTask.new do |test|
36
+ # test.libs << 'test'
37
+ # test.pattern = 'test/**/test_*.rb'
38
+ # test.verbose = true
39
+ # test.rcov_opts << '--exclude "gems/*"'
40
+ # end
41
+ #
42
+ # task :default => :test
43
+
44
+ require 'rdoc/task'
45
+ Rake::RDocTask.new do |rdoc|
46
+ require File.expand_path('../lib/s3_cors_fileupload/version', __FILE__)
47
+ version = S3CorsFileupload::VERSION
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "s3_cors_fileupload #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
54
+
55
+ desc "Open an irb session preloaded with this library"
56
+ task :gem_console do
57
+ sh "irb -I lib -r s3_cors_fileupload.rb"
58
+ end
@@ -0,0 +1,17 @@
1
+ Description:
2
+ Creates a config file, then generates (but does not run) a migration to add a source_files table and
3
+ a corresponding model, as well as a controller, routes, and views for the file uploading.
4
+
5
+ Example:
6
+ rails generate s3_cors_fileupload:install
7
+
8
+ This will create:
9
+ db/migrate/create_source_files.rb
10
+ app/models/source_file.rb
11
+ app/controllers/s3_uploads_controller.rb
12
+ app/assets/javascripts/s3_uploads.js
13
+ app/views/s3_uploads/
14
+ app/views/s3_uploads/_template_download.html.erb
15
+ app/views/s3_uploads/_template_upload.html.erb
16
+ app/views/s3_uploads/_template_uploaded.html.erb
17
+ app/views/s3_uploads/index.html.erb
@@ -0,0 +1,51 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record/migration'
4
+
5
+ module S3CorsFileupload
6
+ module Generators
7
+ class InstallGenerator < ::Rails::Generators::Base
8
+ include ::Rails::Generators::Migration
9
+ extend ActiveRecord::Generators::Migration
10
+
11
+ source_root File.expand_path('../templates', __FILE__)
12
+ # class_option :with_controller, :type => :boolean, :default => false, :desc => "Generate controller, views, and routes"
13
+
14
+ desc('Creates a config file, then generates (but does not run) a migration to add a source_files table and ' +
15
+ 'a corresponding model, as well as a controller, routes, and views for the file uploading.')
16
+
17
+ def create_config_file
18
+ copy_file 'amazon_s3.yml', 'config/amazon_s3.yml'
19
+ end
20
+
21
+ def create_migration_file
22
+ migration_template 'create_source_files.rb', 'db/migrate/create_source_files.rb'
23
+ end
24
+
25
+ def create_model_file
26
+ copy_file 'source_file.rb', 'app/models/source_file.rb'
27
+ end
28
+
29
+ def create_controller
30
+ # if options.with_controller?
31
+ copy_file 's3_uploads_controller.rb', 'app/controllers/s3_uploads_controller.rb'
32
+ copy_file 's3_uploads.js', 'app/assets/javascripts/s3_uploads.js'
33
+ end
34
+
35
+ def create_views
36
+ Dir.foreach(File.expand_path('../templates/views', __FILE__)).reject { |file_name| %w(. ..).include?(file_name) }.each do |file_name|
37
+ copy_file "views/#{file_name}", "app/views/s3_uploads/#{file_name}"
38
+ end
39
+ end
40
+
41
+ def setup_routes
42
+ route(
43
+ ["resources :source_files, :only => [:index, :create, :destroy], :controller => 's3_uploads' do", "\n",
44
+ " get :generate_key, :on => :collection", "\n",
45
+ " end"].join
46
+ )
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ defaults: &defaults
2
+ access_key_id: your_access_key_id
3
+ secret_access_key: your_secret_access_key
4
+ acl: public-read # options: private, public-read, public-read-write, authenticated-read
5
+ max_file_size: 524288000 # 500 megabytes
6
+
7
+ development:
8
+ <<: *defaults
9
+ bucket: your_development_bucket_name
10
+
11
+ test:
12
+ <<: *defaults
13
+ bucket: your_development_bucket_name
14
+
15
+ production:
16
+ <<: *defaults
17
+ bucket: <%= ENV['S3_BUCKET'] || 'your_production_bucket_name_here' %>
@@ -0,0 +1,14 @@
1
+ class CreateSourceFiles < ActiveRecord::Migration
2
+ def change
3
+ create_table :source_files do |t|
4
+ t.string :file_name
5
+ t.string :file_content_type
6
+ t.integer :file_size
7
+ t.string :url
8
+ t.string :key
9
+ t.string :bucket
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,94 @@
1
+ /*
2
+ * s3-cors-file-upload
3
+ * http://github.com/fullbridge-batkins/s3_cors_fileupload
4
+ *
5
+ * Copyright 2012, 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
+ $.ajax({
21
+ url: '/source_files/generate_key',
22
+ type: 'GET',
23
+ dataType: 'json',
24
+ data: {filename: file_name}, // send the file name to the server so it can generate the key param
25
+ async: false,
26
+ success: function(data) {
27
+ // Now that we have our data, we add it to the global s3_upload_hash so that it can be
28
+ // accessed (in the fileuploadsubmit callback) prior to being submitted
29
+ s3_upload_hash[file_name] = {
30
+ key: data.key,
31
+ content_type: content_type
32
+ };
33
+ }
34
+ })
35
+ });
36
+
37
+ // this gets triggered right before a file is about to be sent (and have their form action submitted)
38
+ $('#fileupload').bind('fileuploadsubmit', function (e, data) {
39
+ var file_name = data.files[0].name;
40
+ // transfer the data from the upload-template .form hidden fields to the real form's hidden fields
41
+ var form = $('#fileupload');
42
+ form.find('input[name=key]').val(s3_upload_hash[file_name]['key']);
43
+ form.find('input[name=Content-Type]').val(s3_upload_hash[file_name]['content_type']);
44
+ delete s3_upload_hash[file_name];
45
+ });
46
+
47
+ $('#fileupload').bind('fileuploaddone', function (e, data) {
48
+ // the response will be XML, and can be accessed by calling `data.result`
49
+ //
50
+ // Here is an example of what the XML will look like coming back from S3:
51
+ // <PostResponse>
52
+ // <Location>https://bucket-name.s3.amazonaws.com/uploads%2F3ducks.jpg</Location>
53
+ // <Bucket>bucket-name</Bucket>
54
+ // <Key>uploads/3ducks.jpg</Key>
55
+ // <ETag>"c7902ef289687931f34f92b65afda320"</ETag>
56
+ // </PostResponse>
57
+
58
+ $.post('/source_files',
59
+ {
60
+ 'source_file[url]': $(data.result).find('Location').text(),
61
+ 'source_file[bucket]': $(data.result).find('Bucket').text(),
62
+ 'source_file[key]': $(data.result).find('Key').text(),
63
+ authenticity_token: $('meta[name=csrf-token]').attr('content')
64
+ },
65
+ function(data) {
66
+ $('#upload_files tbody').append(tmpl('template-uploaded', data));
67
+ },
68
+ 'json'
69
+ );
70
+ });
71
+
72
+ // remove the table row containing the source file information from the page
73
+ $('#fileupload').bind('fileuploaddestroyed', function (e, data) {
74
+ var deleted_object_id = data.url.split('/').pop();
75
+ // now remove the element from the page
76
+ $('#source_file_' + deleted_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
+ }
87
+ if (bytes >= 1000000000) {
88
+ return (bytes / 1000000000).toFixed(2) + ' GB';
89
+ }
90
+ if (bytes >= 1000000) {
91
+ return (bytes / 1000000).toFixed(2) + ' MB';
92
+ }
93
+ return (bytes / 1000).toFixed(2) + ' KB';
94
+ }