s3_direct_upload 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +93 -32
- data/app/assets/javascripts/s3_direct_upload.js.coffee +91 -27
- data/lib/s3_direct_upload/form_helper.rb +5 -3
- data/lib/s3_direct_upload/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -6,7 +6,6 @@ Multi file uploading supported by jquery-fileupload.
|
|
6
6
|
Code extracted from Ryan Bates' [gallery-jquery-fileupload](https://github.com/railscasts/383-uploading-to-amazon-s3/tree/master/gallery-jquery-fileupload).
|
7
7
|
|
8
8
|
## Installation
|
9
|
-
|
10
9
|
Add this line to your application's Gemfile:
|
11
10
|
|
12
11
|
gem 's3_direct_upload'
|
@@ -39,27 +38,32 @@ In production the AllowedOrigin key should be your domain.
|
|
39
38
|
|
40
39
|
Add the following js and css to your asset pipeline:
|
41
40
|
|
42
|
-
**application.js**
|
43
|
-
```
|
44
|
-
|
41
|
+
**application.js.coffee**
|
42
|
+
```coffeescript
|
43
|
+
#= require s3_direct_upload
|
45
44
|
```
|
46
45
|
|
47
46
|
**application.css**
|
48
|
-
```
|
47
|
+
```css
|
49
48
|
//= require s3_direct_upload_progress_bars
|
50
49
|
```
|
51
50
|
|
52
51
|
## Usage
|
53
|
-
|
54
|
-
Create a new view that uses the helper:
|
52
|
+
Create a new view that uses the form helper `s3_uploader_form`:
|
55
53
|
```ruby
|
56
|
-
<%= s3_uploader_form post: model_url, as: "model[image_url]" do %>
|
54
|
+
<%= s3_uploader_form post: model_url, as: "model[image_url]", id: "myS3Uploader" do %>
|
57
55
|
<%= file_field_tag :file, multiple: true %>
|
58
56
|
<% end %>
|
59
57
|
```
|
60
58
|
|
59
|
+
Then in your application.js.coffee, call the S3Uploader jQuery plugin on the element you created above:
|
60
|
+
```coffeescript
|
61
|
+
jQuery ->
|
62
|
+
$("#myS3Uploader").S3Uploader()
|
63
|
+
```
|
64
|
+
|
61
65
|
Also place this template in the same view for the progress bars:
|
62
|
-
```
|
66
|
+
```js+erb
|
63
67
|
<script id="template-upload" type="text/x-tmpl">
|
64
68
|
<div class="upload">
|
65
69
|
{%=o.name%}
|
@@ -68,40 +72,94 @@ Also place this template in the same view for the progress bars:
|
|
68
72
|
</script>
|
69
73
|
```
|
70
74
|
|
71
|
-
|
72
|
-
|
75
|
+
## Options for form helper
|
76
|
+
`post:` -> url in which is POST'd to after file is uploaded to S3. Example: model_url
|
73
77
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
`as:` -> parameter value for the POST in which the key will be the URL of the file on S3. If for example this is set to "model[image_url]" then the data posted would be `model[image_url] : http://bucketname.s3.amazonws.com/filename.ext`
|
79
|
+
|
80
|
+
`key:` -> key on s3. defaults to `"uploads/#{SecureRandom.hex}/${filename}"`. needs to be at least `"${filename}"`.
|
81
|
+
|
82
|
+
`acl:` -> acl for files uploaded to s3, defaults to "public-read"
|
83
|
+
|
84
|
+
`max_file_size:` -> maximum file size, defaults to 500.megabytes
|
81
85
|
|
82
|
-
|
83
|
-
After the upload is complete, the script will execute an ajax POST to the model_url given in the `post` option in the form helper.
|
84
|
-
The url to the file on S3 will be passed as a key to whatever is in the `as` option.
|
86
|
+
`id:` -> html id for the form, its recommended that you give the form an id so you can reference with the jQuery plugin.
|
85
87
|
|
86
|
-
|
88
|
+
`class:` -> optional html class for the form.
|
87
89
|
|
90
|
+
|
91
|
+
### Persisting the S3 url
|
92
|
+
It is recommended that you persist the image_url that is sent back from the POST request (to the url given to the `post` option and as the key given in the `as` option). So to access your files later.
|
93
|
+
|
94
|
+
One way to do this is to make sure you have `resources model` in your routes file, and add the `image_url` (or whatever you would like to name it) attribute to your model, and then make sure you have the create action in your controller for that model.
|
95
|
+
|
96
|
+
You could then have your create action render a javascript file like this:
|
88
97
|
**create.js.erb**
|
89
98
|
```ruby
|
90
99
|
<% if @model.new_record? %>
|
91
100
|
alert("Failed to upload model: <%= j @model.errors.full_messages.join(', ').html_safe %>");
|
92
101
|
<% else %>
|
93
|
-
$("#
|
102
|
+
$("#container").append("<%= j render(@model) %>");
|
94
103
|
<% end %>
|
95
104
|
```
|
96
|
-
So that javascript code would be executed after the model instance is created,
|
105
|
+
So that javascript code would be executed after the model instance is created, without a page refresh. See [@rbates's gallery-jquery-fileupload](https://github.com/railscasts/383-uploading-to-amazon-s3/tree/master/gallery-jquery-fileupload)) for an example of that method.
|
97
106
|
|
98
|
-
|
107
|
+
Note: the POST request to the rails app also includes the following parameters `filesize`, `filetype`, `filename` and `filepath`.
|
99
108
|
|
109
|
+
### Advanced Customizations
|
110
|
+
Feel free to override the styling for the progress bars in s3_direct_upload_progress_bars.css, look at the source for inspiration.
|
100
111
|
|
101
|
-
|
112
|
+
Also feel free to write your own js to interface with jquery-file-upload. You might want to do this to do custom validations on the files before it is sent to S3 for example.
|
113
|
+
To do this remove `s3_direct_upload` from your application.js and include the necessary jquery-file-upload scripts in your asset pipeline (they are included in this gem automatically):
|
114
|
+
```cofeescript
|
115
|
+
#= require jquery-fileupload/basic
|
116
|
+
#= require jquery-fileupload/vendor/tmpl
|
117
|
+
```
|
118
|
+
Use the javascript in `s3_direct_upload` as a guide.
|
119
|
+
|
120
|
+
|
121
|
+
## Options for S3Upload jQuery Plugin
|
122
|
+
|
123
|
+
`path` -> manual path for the files on your s3 bucket. Example: `path/to/my/files/on/s3`
|
124
|
+
|
125
|
+
Note: the file path in your s3 bucket will effectively be `path + key`.
|
126
|
+
|
127
|
+
`additional_data` -> You can send additional data to your rails app in the persistence POST request. Example: `{key: value}`
|
128
|
+
|
129
|
+
This would be accessable in your params hash as `params[:key][:value]`
|
130
|
+
|
131
|
+
`before_add` -> Callback function that executes before a file is added to the que. It is passed file object and expects `true` or `false` to be returned.
|
132
|
+
|
133
|
+
This could be useful if you would like to validate the filenames of files to be uploaded for example. If true is returned file will be uploaded as normal, false will cancel the upload.
|
134
|
+
|
135
|
+
### Public methods
|
136
|
+
You can change the settings on your form later on by accessing the jQuery instance:
|
137
|
+
|
138
|
+
```cofeescript
|
139
|
+
jQuery ->
|
140
|
+
v = $("#myS3Uploader").S3Uploader()
|
141
|
+
...
|
142
|
+
v.path("new/path/")
|
143
|
+
v.exta_data("newdata")
|
144
|
+
|
145
|
+
### Global Event Hooks
|
146
|
+
|
147
|
+
When all uploads finish in a batch an `s3_uploads_complete` event will be triggered on `document`, so you could do something like:
|
148
|
+
```javascript
|
149
|
+
$(document).bind('s3_uploads_complete', function(){
|
150
|
+
...
|
151
|
+
alert("All Uploads completed")
|
152
|
+
});
|
153
|
+
````
|
154
|
+
### Example with all options.
|
155
|
+
```cofeescript
|
156
|
+
jQuery ->
|
157
|
+
$("#myS3Uploader").S3Uploader
|
158
|
+
path: 'path/to/my/files/on/s3'
|
159
|
+
additional_data: {key: 'value'}
|
160
|
+
before_add: myCallBackFunction() # must return true or false if set
|
161
|
+
```
|
102
162
|
|
103
|
-
Right now you can only have one upload form on a page.
|
104
|
-
Upload form is hardcoded with id '#fileupload'
|
105
163
|
|
106
164
|
|
107
165
|
## Contributing / TODO
|
@@ -109,10 +167,13 @@ Upload form is hardcoded with id '#fileupload'
|
|
109
167
|
This is just a simple gem that only really provides some javascript and a form helper.
|
110
168
|
This gem could go all sorts of ways based on what people want and how people contribute.
|
111
169
|
Ideas:
|
112
|
-
More specs!
|
113
|
-
More options to control
|
114
|
-
|
115
|
-
|
170
|
+
* More specs!
|
171
|
+
* More options to control file types, ability to batch upload.
|
172
|
+
* More convention over configuration on rails side
|
173
|
+
* Create generators.
|
174
|
+
* Model methods.
|
175
|
+
* Model method to delete files from s3
|
176
|
+
|
116
177
|
|
117
178
|
## Credit
|
118
179
|
|
@@ -1,30 +1,94 @@
|
|
1
1
|
#= require jquery-fileupload/basic
|
2
2
|
#= require jquery-fileupload/vendor/tmpl
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
4
|
+
(($) ->
|
5
|
+
$.fn.S3Uploader = (options) ->
|
6
|
+
|
7
|
+
# support multiple elements
|
8
|
+
if @length > 1
|
9
|
+
@each ->
|
10
|
+
$(this).S3Upleader options
|
11
|
+
|
12
|
+
return this
|
13
|
+
|
14
|
+
$uploadForm = this
|
15
|
+
|
16
|
+
settings =
|
17
|
+
path: ''
|
18
|
+
additional_data: null
|
19
|
+
before_add: null
|
20
|
+
|
21
|
+
settings = $.extend settings, options
|
22
|
+
|
23
|
+
current_files = []
|
24
|
+
|
25
|
+
setUploadForm = ->
|
26
|
+
$uploadForm.fileupload
|
27
|
+
|
28
|
+
add: (e, data) ->
|
29
|
+
current_files.push data
|
30
|
+
file = data.files[0]
|
31
|
+
unless settings.before_add and not settings.before_add(file)
|
32
|
+
data.context = $(tmpl("template-upload", file))
|
33
|
+
$uploadForm.append(data.context)
|
34
|
+
data.submit()
|
35
|
+
|
36
|
+
progress: (e, data) ->
|
37
|
+
if data.context
|
38
|
+
progress = parseInt(data.loaded / data.total * 100, 10)
|
39
|
+
data.context.find('.bar').css('width', progress + '%')
|
40
|
+
|
41
|
+
done: (e, data) ->
|
42
|
+
file = data.files[0]
|
43
|
+
domain = $uploadForm.attr('action')
|
44
|
+
path = settings.path + $uploadForm.find('input[name=key]').val().replace('/${filename}', '')
|
45
|
+
to = $uploadForm.data('post')
|
46
|
+
content = {}
|
47
|
+
content[$uploadForm.data('as')] = domain + path + '/' + file.name
|
48
|
+
content.filename = file.name
|
49
|
+
content.filepath = path
|
50
|
+
if settings.additional_data
|
51
|
+
content = $.extend content, settings.additional_data
|
52
|
+
if 'size' of file
|
53
|
+
content.file_size = file.size
|
54
|
+
if 'type' of file
|
55
|
+
content.file_type = file.type
|
56
|
+
|
57
|
+
$.post(to, content)
|
58
|
+
data.context.remove() if data.context # remove progress bar
|
59
|
+
|
60
|
+
current_files.splice($.inArray(data, current_files), 1) # remove that element from the array
|
61
|
+
if current_files.length == 0
|
62
|
+
$(document).trigger("s3_uploads_complete")
|
63
|
+
|
64
|
+
fail: (e, data) ->
|
65
|
+
alert("#{data.files[0].name} failed to upload.")
|
66
|
+
console.log("Upload failed:")
|
67
|
+
console.log(data)
|
68
|
+
|
69
|
+
formData: (form) ->
|
70
|
+
data = form.serializeArray()
|
71
|
+
fileType = ""
|
72
|
+
if "type" of @files[0]
|
73
|
+
fileType = @files[0].type
|
74
|
+
data.push
|
75
|
+
name: "Content-Type"
|
76
|
+
value: fileType
|
77
|
+
|
78
|
+
data[1].value = settings.path + data[1].value
|
79
|
+
|
80
|
+
data
|
81
|
+
|
82
|
+
#public methods
|
83
|
+
@initialize = ->
|
84
|
+
setUploadForm()
|
85
|
+
this
|
86
|
+
|
87
|
+
@path = (new_path) ->
|
88
|
+
settings.path = new_path
|
89
|
+
|
90
|
+
@additional_data = (new_data) ->
|
91
|
+
settings.additional_data = additional_data
|
92
|
+
|
93
|
+
@initialize()
|
94
|
+
) jQuery
|
@@ -12,20 +12,21 @@ module S3DirectUpload
|
|
12
12
|
class S3Uploader
|
13
13
|
def initialize(options)
|
14
14
|
@options = options.reverse_merge(
|
15
|
-
id: "fileupload",
|
16
15
|
aws_access_key_id: S3DirectUpload.config.access_key_id,
|
17
16
|
aws_secret_access_key: S3DirectUpload.config.secret_access_key,
|
18
17
|
bucket: S3DirectUpload.config.bucket,
|
19
18
|
acl: "public-read",
|
20
19
|
expiration: 10.hours.from_now,
|
21
20
|
max_file_size: 500.megabytes,
|
22
|
-
as: "file"
|
21
|
+
as: "file",
|
22
|
+
key: key
|
23
23
|
)
|
24
24
|
end
|
25
25
|
|
26
26
|
def form_options
|
27
27
|
{
|
28
28
|
id: @options[:id],
|
29
|
+
class: @options[:class],
|
29
30
|
method: "post",
|
30
31
|
authenticity_token: false,
|
31
32
|
multipart: true,
|
@@ -38,7 +39,7 @@ module S3DirectUpload
|
|
38
39
|
|
39
40
|
def fields
|
40
41
|
{
|
41
|
-
:key => key,
|
42
|
+
:key => @options[:key] || key,
|
42
43
|
:acl => @options[:acl],
|
43
44
|
:policy => policy,
|
44
45
|
:signature => signature,
|
@@ -65,6 +66,7 @@ module S3DirectUpload
|
|
65
66
|
["starts-with", "$utf8", ""],
|
66
67
|
["starts-with", "$key", ""],
|
67
68
|
["content-length-range", 0, @options[:max_file_size]],
|
69
|
+
["starts-with","$Content-Type",""],
|
68
70
|
{bucket: @options[:bucket]},
|
69
71
|
{acl: @options[:acl]}
|
70
72
|
]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: s3_direct_upload
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09
|
12
|
+
date: 2012-10-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|