uploader 0.1.3
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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +275 -0
- data/Rakefile +66 -0
- data/TODO +2 -0
- data/VERSION +1 -0
- data/app/controllers/uploader/uploads_controller.rb +122 -0
- data/app/helpers/uploader_helper.rb +17 -0
- data/app/views/uploads/_swf_javascript.html.erb +63 -0
- data/app/views/uploads/_swf_upload.html.erb +32 -0
- data/config/uploader_routes.rb +3 -0
- data/db/migrate/20090517040220_create_uploads.rb +38 -0
- data/lib/active_record/acts/uploader_upload.rb +235 -0
- data/lib/uploader/exceptions.rb +5 -0
- data/lib/uploader/initialize_routes.rb +8 -0
- data/lib/uploader/middleware/flash_session_cookie_middleware.rb +18 -0
- data/lib/uploader/mime_type_groups.rb +18 -0
- data/lib/uploader/tasks.rb +36 -0
- data/lib/uploader.rb +24 -0
- data/locales/ar.yml +17 -0
- data/locales/bg.yml +17 -0
- data/locales/ca.yml +17 -0
- data/locales/cs.yml +17 -0
- data/locales/da.yml +17 -0
- data/locales/de.yml +17 -0
- data/locales/el.yml +17 -0
- data/locales/en.yml +16 -0
- data/locales/es.yml +17 -0
- data/locales/fr.yml +17 -0
- data/locales/it.yml +17 -0
- data/locales/iw.yml +17 -0
- data/locales/ja.yml +17 -0
- data/locales/ko.yml +17 -0
- data/locales/lt.yml +17 -0
- data/locales/lv.yml +17 -0
- data/locales/nl.yml +17 -0
- data/locales/no.yml +18 -0
- data/locales/pl.yml +17 -0
- data/locales/pt.yml +17 -0
- data/locales/ro.yml +17 -0
- data/locales/ru.yml +17 -0
- data/locales/sk.yml +17 -0
- data/locales/sl.yml +17 -0
- data/locales/sr.yml +17 -0
- data/locales/sv.yml +17 -0
- data/locales/tl.yml +17 -0
- data/locales/uk.yml +17 -0
- data/locales/vi.yml +17 -0
- data/locales/zh-CN.yml +17 -0
- data/locales/zh-TW.yml +17 -0
- data/locales/zh.yml +17 -0
- data/pkg/uploader-0.1.0.gem +0 -0
- data/pkg/uploader-0.1.1.gem +0 -0
- data/pkg/uploader-0.1.2.gem +0 -0
- data/public/images/SWFUploadButton.png +0 -0
- data/public/images/file_icons/excel.gif +0 -0
- data/public/images/file_icons/file.gif +0 -0
- data/public/images/file_icons/mp3.gif +0 -0
- data/public/images/file_icons/pdf.gif +0 -0
- data/public/images/file_icons/text.gif +0 -0
- data/public/images/file_icons/word.gif +0 -0
- data/public/javascripts/swfupload/fileprogress.js +151 -0
- data/public/javascripts/swfupload/handlers.js +206 -0
- data/public/javascripts/swfupload/swfupload.cookies.js +53 -0
- data/public/javascripts/swfupload/swfupload.js +945 -0
- data/public/javascripts/swfupload/swfupload.queue.js +77 -0
- data/public/javascripts/swfupload/swfupload.swfobject.js +110 -0
- data/public/stylesheets/swfupload.css +26 -0
- data/public/swf/swfupload.swf +0 -0
- data/rails/init.rb +10 -0
- data/tasks/rails.rake +2 -0
- data/test/test_helper.rb +3 -0
- data/test/unit/upload_test.rb +5 -0
- data/uninstall.rb +0 -0
- data/uploader.gemspec +127 -0
- metadata +128 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Justin Ball
|
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
= Uploader
|
2
|
+
|
3
|
+
Uploader makes it easy to integrate multiple file uploads into your application using SWFUpload
|
4
|
+
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
=== Install Dependancies:
|
9
|
+
sudo gem install mime-types
|
10
|
+
|
11
|
+
|
12
|
+
=== Install the gem:
|
13
|
+
sudo gem install uploader
|
14
|
+
|
15
|
+
|
16
|
+
=== Add the gem to environment.rb
|
17
|
+
config.gem 'uploader'
|
18
|
+
|
19
|
+
|
20
|
+
=== Create a model for uploads.
|
21
|
+
We recommend creating a model called upload.rb. acts_as_uploader accepts all valid options for paperclip via :has_attached_file => {}
|
22
|
+
|
23
|
+
class Upload < ActiveRecord::Base
|
24
|
+
acts_as_uploader :enable_s3 => false,
|
25
|
+
:has_attached_file => {
|
26
|
+
:url => "/system/:attachment/:id_partition/:style/:basename.:extension",
|
27
|
+
:path => ":rails_root/public/system/:attachment/:id_partition/:style/:basename.:extension",
|
28
|
+
:styles => { :icon => "30x30!",
|
29
|
+
:thumb => "100>",
|
30
|
+
:small => "150>",
|
31
|
+
:medium => "300>",
|
32
|
+
:large => "660>"},
|
33
|
+
:default_url => "/images/profile_default.jpg",
|
34
|
+
:storage => :s3,
|
35
|
+
:s3_credentials => File.join(RAILS_ROOT, 'config', 's3.yml'),
|
36
|
+
:bucket => "assets.#{SITE[:domain]}",
|
37
|
+
:s3_host_alias => "assets.#{SITE[:domain]}",
|
38
|
+
:convert_options => {
|
39
|
+
:all => '-quality 80'
|
40
|
+
}
|
41
|
+
|
42
|
+
# only allow images:
|
43
|
+
# validates_attachment_content_type :file, :content_type => ['image/jpeg', 'image/pjpeg', 'image/jpg']
|
44
|
+
|
45
|
+
# The following method is implemented in 'acts_as_uploader'. This is the method destroy will check to see if
|
46
|
+
# the user has permission to delete the object. Add additional logic as needed or if the existing logic
|
47
|
+
# looks fine then feel free to delete this comment and the can_edit? method.
|
48
|
+
def can_edit?(check_user)
|
49
|
+
return false if user.blank?
|
50
|
+
check_user == self.user
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
=== Add multiple file uploads to one of your models
|
57
|
+
|
58
|
+
Your uploads will need a parent object to attach to. For example, a user might have many files:
|
59
|
+
|
60
|
+
class User < ActiveRecord::Base
|
61
|
+
has_many :uploads, :as => :uploadable, :order => 'created_at desc', :dependent => :destroy
|
62
|
+
|
63
|
+
def can_upload?(check_user)
|
64
|
+
self == check_user
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
or a photo album might have many photos
|
69
|
+
|
70
|
+
class PhotoAlbum < ActiveRecord::Base
|
71
|
+
has_many :photos, :as => :uploadable, :order => 'created_at desc', :dependent => :destroy
|
72
|
+
|
73
|
+
def can_upload?(check_user)
|
74
|
+
self.editors.include?(check_user)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
Note that in both examples there is an implementation of 'can_upload?'. This method must be
|
79
|
+
included in any parent object and will control who has permission to upload files.
|
80
|
+
|
81
|
+
=== The application controller
|
82
|
+
Be sure you have turned on protect from forgery. This is required for uploader to get the appropriate tokens
|
83
|
+
from your Rails application. It is also a good idea and is the default in new Rails applications.
|
84
|
+
|
85
|
+
protect_from_forgery # See ActionController::RequestForgeryProtection for details
|
86
|
+
|
87
|
+
=== The uploads controller
|
88
|
+
You can modify the upload controller behavior by inheriting from the uploader controller. For example, you might want to
|
89
|
+
require that users be logged in to upload a file. There are a number of methods in the uploads controller that contain
|
90
|
+
default functionality that you may consider overriding.
|
91
|
+
|
92
|
+
Be sure to modify your routes file. Add the following line to ensure that your application uses the new uploads
|
93
|
+
controller instead of directly using the one inside the gem:
|
94
|
+
|
95
|
+
map.resources :uploads, :collection => { :swfupload => :post }
|
96
|
+
|
97
|
+
|
98
|
+
class UploadsController < Uploader::UploadsController
|
99
|
+
|
100
|
+
before_filter :login_required
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
# The default 'get_upload_text' method throws an exception. You must override this method in your controller. It
|
105
|
+
# is used by the swf upload call to generate the html to be returned to the client.
|
106
|
+
# Here's an example:
|
107
|
+
def get_upload_text(upload)
|
108
|
+
render_to_string( :partial => 'uploads/upload_row', :object => upload, :locals => { :parent => @parent } )
|
109
|
+
end
|
110
|
+
|
111
|
+
# The existing method will handle most cases but you might choose a different message or a different redirect:
|
112
|
+
def permission_denied
|
113
|
+
message = t("uploader.permission_denied")
|
114
|
+
respond_to do |format|
|
115
|
+
format.html do
|
116
|
+
flash[:notice] = message
|
117
|
+
redirect_to get_redirect
|
118
|
+
end
|
119
|
+
format.js { render :text => message }
|
120
|
+
format.json { render :json => { :success => false, :message => message } }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Simply attempts to redirect to the parent object. You might want to build something more sophisticated that
|
125
|
+
# redirect to different areas of you site depending on the type of object that was uploaded or on based on the parent.
|
126
|
+
def get_redirect
|
127
|
+
@parent
|
128
|
+
end
|
129
|
+
|
130
|
+
# The default action is to call 'can_upload?' on the parent object. Be sure to implement 'can_upload?(check_user) on
|
131
|
+
# your parent objects
|
132
|
+
def has_permission_to_upload(user, upload_parent)
|
133
|
+
upload_parent.can_upload?(user)
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
# By default the controller will use a model named 'Upload' to do a destroy. If you want to use a different model
|
138
|
+
# you'll need to override 'set_upload_for_destroy in your controller to find the object using a different object.
|
139
|
+
# For example:
|
140
|
+
def set_upload_for_destroy
|
141
|
+
@upload = Photo.find(params[:id])
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
=== Other Methods
|
148
|
+
|
149
|
+
uploader assumes that you have a method called 'redirect_back_or_default' which is common in many Rails projects. This method
|
150
|
+
is called upon completion of destroy or created when the requested format is 'html'. A simple implementation of this method is listed
|
151
|
+
below:
|
152
|
+
|
153
|
+
def redirect_back_or_default(default)
|
154
|
+
redirect_to(session[:return_to] || default)
|
155
|
+
session[:return_to] = nil
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
=== Configure your views.
|
160
|
+
You'll need something like this in your layout so that uploader can add in the required css and javascript files.
|
161
|
+
|
162
|
+
<%= yield :head -%>
|
163
|
+
|
164
|
+
Then to add an upload form:
|
165
|
+
<%= upload_form(parent_object) %>
|
166
|
+
parent_object should be the object which owns the uploads. ie a user, photo_album, etc.
|
167
|
+
|
168
|
+
=== Rake Tasks
|
169
|
+
|
170
|
+
Add the rake tasks for uploader to your project. You will need to add the following to your applications's Rakefile
|
171
|
+
|
172
|
+
require 'uploader'
|
173
|
+
require 'uploader/tasks'
|
174
|
+
|
175
|
+
Then run:
|
176
|
+
rake uploader:sync
|
177
|
+
|
178
|
+
Last run:
|
179
|
+
rake db:migrate
|
180
|
+
This will create an uploads table for you. If you selected a different name for your model you will need to modify the migration accordingly.
|
181
|
+
== WARNING
|
182
|
+
The migration will drop any existing 'uploads' table you have in place
|
183
|
+
|
184
|
+
|
185
|
+
That will copy all the required javascript and asset files into your project
|
186
|
+
|
187
|
+
|
188
|
+
== Amazon s3
|
189
|
+
|
190
|
+
|
191
|
+
If you'd like to store your uploads on Amazon's S3 service there are a few extra steps involved. See the example file above
|
192
|
+
to view the options in context.
|
193
|
+
|
194
|
+
=== Turn on s3
|
195
|
+
Set the enable_s3 option to true in acts_as_uploader
|
196
|
+
:enable_s3 => true
|
197
|
+
|
198
|
+
Pass your s3 credentials into acts_as_uploader
|
199
|
+
:has_attached_file => { :s3_credentials => File.join(RAILS_ROOT, 'config', 's3.yml') }
|
200
|
+
|
201
|
+
=== Setup your credentials
|
202
|
+
Create a file named s3.yml in your configuration directory and add the following lines:
|
203
|
+
|
204
|
+
access_key_id: PUT YOUR KEY HERE
|
205
|
+
secret_access_key: PUT YOUR SECRET ACCESS KEY HERE
|
206
|
+
|
207
|
+
|
208
|
+
=== Turn on the Daemon process
|
209
|
+
There are a number of timing issues that you will run into if you attempt to upload files directly to s3. To overcome that
|
210
|
+
problem uploader includes a daemon process which will send the files to Amazon asynchronously. Note that the uploader
|
211
|
+
will leave your local copy in place.
|
212
|
+
TODO docs for Daemon
|
213
|
+
|
214
|
+
|
215
|
+
== Other Stuff
|
216
|
+
|
217
|
+
If you'd like to add an ajax delete to your uploads page this code might come in handy.
|
218
|
+
|
219
|
+
Say you have chosen to display your upload in a table. Your code might look like the following. Note that there are a number of assumptions made in this code. Modify it to suite your needs.
|
220
|
+
|
221
|
+
<tr id="<%= upload_row.dom_id %>" class="delete-container <%= cycle('odd', 'even') %>" <%=style-%> >
|
222
|
+
<td><div class="file-icon"><%= image_tag upload_row.icon -%></div></td>
|
223
|
+
<td><a href="<%=upload_row.file.url%>"><%= truncate(sanitize(upload_row.file_name), 100) %></a></td>
|
224
|
+
<td><%= upload_row.created_at.to_s(:long) -%></td>
|
225
|
+
<td>
|
226
|
+
<% if parent.can_edit?(current_user) -%>
|
227
|
+
<% form_for(:upload, :url => upload_path(upload_row.id), :html => { :class => "delete-form", :method => :delete} ) do |f| -%>
|
228
|
+
<%= image_submit_tag '/images/icons/delete.png', {:id => 'submit-comment', :title => t('general.delete_file'), :class => 'submit-delete', :width => '12', :height => '12', :alt => t('general.delete_file') } %>
|
229
|
+
<% end -%>
|
230
|
+
<% if !style.empty? -%>
|
231
|
+
<script type="text/javascript" language="JavaScript">
|
232
|
+
jQuery("#<%= upload_row.dom_id %>").fadeIn("slow");
|
233
|
+
</script>
|
234
|
+
<% end -%>
|
235
|
+
<% end -%>
|
236
|
+
</td>
|
237
|
+
</tr>
|
238
|
+
|
239
|
+
|
240
|
+
I put the following in my main upload view
|
241
|
+
<% content_for :javascript do -%>
|
242
|
+
|
243
|
+
setup_submit_delete();
|
244
|
+
|
245
|
+
function upload_completed_callback(data){
|
246
|
+
jQuery('#upload-list').prepend(data);
|
247
|
+
setup_submit_delete();
|
248
|
+
}
|
249
|
+
<% end -%>
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
The following jQuery code will do an ajax delete for you
|
254
|
+
|
255
|
+
function setup_submit_delete(){
|
256
|
+
jQuery(".submit-delete").click(function() {
|
257
|
+
// if(!confirm("Are you sure?")){
|
258
|
+
// return false;
|
259
|
+
// }
|
260
|
+
jQuery(this).parents('.delete-container').fadeOut();
|
261
|
+
var form = jQuery(this).parents('form');
|
262
|
+
jQuery.post(form.attr('action') + '.json', form.serialize(),
|
263
|
+
function(data){
|
264
|
+
var json = eval('(' + data + ')');
|
265
|
+
if(!json.success){
|
266
|
+
jQuery.jGrowl.info(json.message);
|
267
|
+
}
|
268
|
+
});
|
269
|
+
return false;
|
270
|
+
});
|
271
|
+
}
|
272
|
+
|
273
|
+
|
274
|
+
|
275
|
+
Copyright (c) 2009 Justin Ball, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the uploader plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the uploader plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'Uploader'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'jeweler'
|
27
|
+
Jeweler::Tasks.new do |gemspec|
|
28
|
+
gemspec.name = "uploader"
|
29
|
+
gemspec.summary = "SWFUpload + Paperclip wrapped in an engine with love."
|
30
|
+
gemspec.email = "justinball@gmail.com"
|
31
|
+
gemspec.homepage = "http://github.com/jbasdf/uploader"
|
32
|
+
gemspec.description = "Uploader gem that makes it simple add multiple file uploads to your Rails project using SWFUpload and Paperclip"
|
33
|
+
gemspec.authors = ["Justin Ball", "David South"]
|
34
|
+
gemspec.files.include %w( tasks/rails.rake lib/uploader/*.rb lib/uploader/middleware/*.rb db/migrate/*.rb public/images/file_icons/* app/views/uploads/* )
|
35
|
+
gemspec.rubyforge_project = 'uploader'
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
39
|
+
end
|
40
|
+
|
41
|
+
# rubyforge tasks
|
42
|
+
begin
|
43
|
+
require 'rake/contrib/sshpublisher'
|
44
|
+
namespace :rubyforge do
|
45
|
+
|
46
|
+
desc "Release gem and RDoc documentation to RubyForge"
|
47
|
+
task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
|
48
|
+
|
49
|
+
namespace :release do
|
50
|
+
desc "Publish RDoc to RubyForge."
|
51
|
+
task :docs => [:rdoc] do
|
52
|
+
config = YAML.load(
|
53
|
+
File.read(File.expand_path('~/.rubyforge/user-config.yml'))
|
54
|
+
)
|
55
|
+
|
56
|
+
host = "#{config['username']}@rubyforge.org"
|
57
|
+
remote_dir = "/var/www/gforge-projects/the-perfect-gem/"
|
58
|
+
local_dir = 'rdoc'
|
59
|
+
|
60
|
+
Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
rescue LoadError
|
65
|
+
puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
|
66
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.3
|
@@ -0,0 +1,122 @@
|
|
1
|
+
class Uploader::UploadsController < ApplicationController
|
2
|
+
unloadable
|
3
|
+
|
4
|
+
before_filter :get_parent, :only => [:create, :swfupload]
|
5
|
+
before_filter :set_upload_for_destroy, :only => [:destroy]
|
6
|
+
|
7
|
+
def create
|
8
|
+
# Standard, one-at-a-time, upload action
|
9
|
+
@upload = @parent.uploads.build(params[:upload])
|
10
|
+
@upload.creator = current_user
|
11
|
+
@upload.save!
|
12
|
+
message = t('uploader.successful_upload')
|
13
|
+
upload_json = basic_uploads_json(@upload)
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html do
|
17
|
+
flash[:notice] = message
|
18
|
+
redirect_to redirect_back_or_default(get_redirect)
|
19
|
+
end
|
20
|
+
format.js { render :text => get_upload_text(@upload) }
|
21
|
+
format.json { render :json => upload_json }
|
22
|
+
end
|
23
|
+
rescue => ex
|
24
|
+
message = t('uploader.standard_file_upload_error', :error => ex)
|
25
|
+
respond_to do |format|
|
26
|
+
format.html do
|
27
|
+
flash[:notice] = message
|
28
|
+
redirect_back_or_default(get_redirect)
|
29
|
+
end
|
30
|
+
format.js { render :text => message }
|
31
|
+
format.json { render :json => { :success => false, :message => message } }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def swfupload
|
36
|
+
@upload = @parent.uploads.build
|
37
|
+
@upload.is_public = true if params[:is_public] == true
|
38
|
+
@upload.creator = current_user
|
39
|
+
@upload.swfupload_local = params[:Filedata]
|
40
|
+
@upload.save!
|
41
|
+
@parent.uploads << @upload
|
42
|
+
respond_to do |format|
|
43
|
+
format.js { render :text => get_upload_text(@upload) }
|
44
|
+
format.json { render :json => basic_uploads_json(@upload) }
|
45
|
+
end
|
46
|
+
rescue => ex
|
47
|
+
message = t('uploader.standard_file_upload_error', :error => ex)
|
48
|
+
respond_to do |format|
|
49
|
+
format.js { render :text => message }
|
50
|
+
format.json { render :json => { :success => false, :message => message } }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy
|
55
|
+
@parent = @upload.uploadable # set this for redirect
|
56
|
+
if @upload.can_edit?(current_user)
|
57
|
+
@upload.destroy
|
58
|
+
message = t('uploader.file_deleted')
|
59
|
+
success = true
|
60
|
+
else
|
61
|
+
message = t("uploader.file_delete_permission_denied")
|
62
|
+
success = false
|
63
|
+
end
|
64
|
+
respond_to do |format|
|
65
|
+
format.html do
|
66
|
+
flash[:notice] = message
|
67
|
+
redirect_back_or_default(get_redirect)
|
68
|
+
end
|
69
|
+
format.js { render :text => message }
|
70
|
+
format.json { render :json => { :success => success, :message => message } }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def get_upload_text(upload)
|
77
|
+
raise 'implement get_upload_text in your controller'
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_upload_for_destroy
|
81
|
+
@upload = Upload.find(params[:id])
|
82
|
+
end
|
83
|
+
|
84
|
+
def permission_denied
|
85
|
+
message = t("uploader.permission_denied")
|
86
|
+
respond_to do |format|
|
87
|
+
format.html do
|
88
|
+
flash[:notice] = message
|
89
|
+
redirect_to get_redirect
|
90
|
+
end
|
91
|
+
format.js { render :text => message }
|
92
|
+
format.json { render :json => { :success => false, :message => message } }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# override this method in your controller to set the redirect file upload completion
|
97
|
+
# alternatively set redirect_back_or_default
|
98
|
+
def get_redirect
|
99
|
+
@parent
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_parent
|
103
|
+
if !params[:parent_type] || !params[:parent_id]
|
104
|
+
raise t('uploader.missing_parent_id_error')
|
105
|
+
return
|
106
|
+
end
|
107
|
+
@klass = params[:parent_type].to_s.capitalize.constantize
|
108
|
+
@parent = @klass.find(params[:parent_id])
|
109
|
+
unless has_permission_to_upload(current_user, @parent)
|
110
|
+
permission_denied
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def has_permission_to_upload(user, upload_parent)
|
115
|
+
upload_parent.can_upload?(user)
|
116
|
+
end
|
117
|
+
|
118
|
+
def basic_uploads_json(upload)
|
119
|
+
upload.to_json(:only => [:id, :file_name], :methods => [:icon])
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module UploaderHelper
|
2
|
+
|
3
|
+
# parent is the object to which the uploads will be attached
|
4
|
+
def upload_form(parent, display_upload_indicators = true)
|
5
|
+
render :partial => 'uploads/swf_upload', :locals => {:parent => parent, :display_upload_indicators => display_upload_indicators}
|
6
|
+
end
|
7
|
+
|
8
|
+
def new_upload_path_with_session_information(upload_parent)
|
9
|
+
session_key = ActionController::Base.session_options[:key]
|
10
|
+
swfupload_uploads_path({session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token}.merge(make_parent_params(upload_parent)))
|
11
|
+
end
|
12
|
+
|
13
|
+
def make_parent_params(parent)
|
14
|
+
{ :parent_id => parent.id, :parent_type => parent.class.to_s }
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<% content_for :head do -%>
|
2
|
+
<%= javascript_include_tag %w{
|
3
|
+
swfupload/swfupload.js
|
4
|
+
swfupload/swfupload.swfobject
|
5
|
+
swfupload/swfupload.cookies
|
6
|
+
swfupload/swfupload.queue
|
7
|
+
swfupload/fileprogress.js
|
8
|
+
swfupload/handlers.js }, :cache => 'swf_js_cached' %>
|
9
|
+
<%= stylesheet_link_tag 'swfupload' %>
|
10
|
+
|
11
|
+
<script type='text/javascript'>
|
12
|
+
|
13
|
+
var swfu;
|
14
|
+
|
15
|
+
SWFUpload.onload = function () {
|
16
|
+
var settings = {
|
17
|
+
|
18
|
+
flash_url : '/swf/swfupload.swf',
|
19
|
+
upload_url: '<%= new_upload_path_with_session_information(parent) %>',
|
20
|
+
|
21
|
+
file_size_limit : "100 MB",
|
22
|
+
file_types : "*.*",
|
23
|
+
file_types_description : "All Files",
|
24
|
+
file_upload_limit : 100,
|
25
|
+
file_queue_limit : 0,
|
26
|
+
post_params : {
|
27
|
+
authenticity_token : '<%= u form_authenticity_token.inspect -%>',
|
28
|
+
},
|
29
|
+
custom_settings : {
|
30
|
+
<%= 'progressTarget : "swf_fs_upload_progress",' if display_upload_indicators -%>
|
31
|
+
cancelButtonId : "swf_cancel_button"
|
32
|
+
},
|
33
|
+
debug: false,
|
34
|
+
|
35
|
+
// Button Settings
|
36
|
+
button_image_url : "/images/SWFUploadButton.png", // Relative to the SWF file
|
37
|
+
button_placeholder_id : "swf_button_holder",
|
38
|
+
button_width: 61,
|
39
|
+
button_height: 22,
|
40
|
+
|
41
|
+
// The event handler functions are defined in handlers.js
|
42
|
+
swfupload_loaded_handler : swfUploadLoaded,
|
43
|
+
file_queued_handler : fileQueued,
|
44
|
+
file_queue_error_handler : fileQueueError,
|
45
|
+
file_dialog_complete_handler : fileDialogComplete,
|
46
|
+
upload_start_handler : uploadStart,
|
47
|
+
upload_progress_handler : uploadProgress,
|
48
|
+
upload_error_handler : uploadError,
|
49
|
+
upload_success_handler : uploadSuccess,
|
50
|
+
upload_complete_handler : uploadComplete,
|
51
|
+
queue_complete_handler : queueComplete, // Queue plugin event
|
52
|
+
|
53
|
+
// SWFObject settings
|
54
|
+
minimum_flash_version : "9.0.28",
|
55
|
+
swfupload_pre_load_handler : swfUploadPreLoad,
|
56
|
+
swfupload_load_failed_handler : swfUploadLoadFailed
|
57
|
+
};
|
58
|
+
|
59
|
+
swfu = new SWFUpload(settings);
|
60
|
+
}
|
61
|
+
|
62
|
+
</script>
|
63
|
+
<% end -%>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<div id="degraded_container" style="display:none;">
|
2
|
+
<% form_for :upload, :url => uploads_path(make_parent_params(parent)), :html => { :multipart => true } do |f| -%>
|
3
|
+
<p><%= f.file_field :uploaded_data, :size => 25 %></p>
|
4
|
+
<%= submit_tag t('uploader.upload_file') %>
|
5
|
+
<% end %>
|
6
|
+
</div>
|
7
|
+
<div id="swfupload_container">
|
8
|
+
<form>
|
9
|
+
<div id="swf_upload_UI">
|
10
|
+
<p><span id="swf_button_holder"></span></p>
|
11
|
+
<div id="swf_fs_upload_progress">
|
12
|
+
<span class="legend"></span>
|
13
|
+
<input id="swf_cancel_button" type="button" value="<%=t('uploader.cancel_all')%>" style="display:none;" />
|
14
|
+
<p id="divStatus"></p>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<noscript class="swf-error-msg">
|
18
|
+
<%= t('uploader.javascript_not_enabled') %>
|
19
|
+
</noscript>
|
20
|
+
<div id="swf_loading_content" class="swf-error-msg" style="display:none;">
|
21
|
+
<%= t('uploader.swf_loading') %>
|
22
|
+
</div>
|
23
|
+
<div id="swf_long_loading" class="swf-error-msg" style="display:none;">
|
24
|
+
<%= t('uploader.swf_taking_to_long') %>
|
25
|
+
</div>
|
26
|
+
<div id="swf_alternate_content" class="swf-error-msg" style="display: none;">
|
27
|
+
<%= t('uploader.swf_not_loading', :url => '<a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash">Adobe Website</a>') %>
|
28
|
+
</div>
|
29
|
+
</form>
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<%= render :partial => 'uploads/swf_javascript', :locals => { :parent => parent, :display_upload_indicators => display_upload_indicators } %>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class CreateUploads < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :uploads, :force => true do |t|
|
4
|
+
t.integer :creator_id
|
5
|
+
t.string :name
|
6
|
+
t.string :caption, :limit => 1000
|
7
|
+
t.text :description
|
8
|
+
t.boolean :is_public, :default => true
|
9
|
+
t.integer :uploadable_id
|
10
|
+
t.string :uploadable_type
|
11
|
+
t.string :width
|
12
|
+
t.string :height
|
13
|
+
|
14
|
+
t.string :local_file_name
|
15
|
+
t.string :local_content_type
|
16
|
+
t.integer :local_file_size
|
17
|
+
t.datetime :local_updated_at
|
18
|
+
|
19
|
+
t.string :remote_file_name
|
20
|
+
t.string :remote_content_type
|
21
|
+
t.integer :remote_file_size
|
22
|
+
t.datetime :remote_updated_at
|
23
|
+
|
24
|
+
t.timestamps
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index :uploads, ["creator_id"]
|
28
|
+
add_index :uploads, ["uploadable_id"]
|
29
|
+
add_index :uploads, ["uploadable_type"]
|
30
|
+
add_index :uploads, ["local_content_type"]
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.down
|
35
|
+
drop_table :uploads
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|