upr 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/GIT-VERSION-GEN +1 -1
  2. data/GNUmakefile +1 -1
  3. data/LICENSE +9 -4
  4. data/README +29 -13
  5. data/examples/rails_app-2.3.4/app/controllers/application_controller.rb +8 -1
  6. data/examples/rails_app-2.3.4/app/controllers/files_controller.rb +35 -12
  7. data/examples/rails_app-2.3.4/app/controllers/progress_controller.rb +11 -0
  8. data/examples/rails_app-2.3.4/app/models/upr_status.rb +34 -10
  9. data/examples/rails_app-2.3.4/app/views/files/index.html.erb +14 -4
  10. data/examples/rails_app-2.3.4/app/views/files/new.html.erb +71 -0
  11. data/examples/rails_app-2.3.4/app/views/files/pull.html.erb +60 -0
  12. data/examples/rails_app-2.3.4/config.ru +3 -0
  13. data/examples/rails_app-2.3.4/config/initializers/ruby_19_compat.rb +26 -0
  14. data/examples/rails_app-2.3.4/public/javascripts/ajax_pull/ajax_pull.js +85 -0
  15. data/examples/rails_app-2.3.4/public/javascripts/ajax_pull/prototype-1_5_1.js +3271 -0
  16. data/examples/rails_app-2.3.4/public/javascripts/ajax_pull/upload_progress.js +139 -0
  17. data/examples/rails_app-2.3.4/public/javascripts/jquery.js +32 -0
  18. data/examples/rails_app-2.3.4/public/javascripts/jquery.uploadProgress.js +116 -0
  19. data/examples/rails_app-2.3.4/public/stylesheets/site.css +41 -0
  20. data/examples/rails_app-2.3.4/rainbows_config.rb +1 -1
  21. data/examples/rails_app-2.3.4/test/fixtures/upr_statuses.yml +22 -0
  22. data/examples/rails_app-2.3.4/test/unit/upr_status_test.rb +41 -0
  23. data/lib/upr.rb +4 -5
  24. data/lib/upr/input_wrapper.rb +17 -13
  25. data/lib/upr/json.rb +143 -0
  26. data/lib/upr/monitor.rb +18 -6
  27. data/lib/upr/params.rb +24 -0
  28. data/lib/upr/status.rb +9 -0
  29. data/lib/upr/status_methods.rb +13 -0
  30. data/test/test_monitor.rb +58 -0
  31. data/upr.gemspec +1 -0
  32. metadata +37 -5
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.1.0.GIT
4
+ DEF_VER=v0.2.0.GIT
5
5
 
6
6
  LF='
7
7
  '
@@ -55,7 +55,7 @@ NEWS: GIT-VERSION-FILE
55
55
  $(rake) -s news_rdoc > $@+
56
56
  mv $@+ $@
57
57
 
58
- SINCE =
58
+ SINCE = 0.1.0
59
59
  ChangeLog: log_range = $(shell test -n "$(SINCE)" && echo v$(SINCE)..)
60
60
  ChangeLog: GIT-VERSION-FILE
61
61
  @echo "ChangeLog from $(GIT_URL) ($(SINCE)..$(GIT_VERSION))" > $@+
data/LICENSE CHANGED
@@ -1,8 +1,13 @@
1
1
  Upload Progress for Rack (upr) is copyrighted Free Software by all
2
- contributors, see the logs in revision control for all of them. You can
3
- redistribute it and/or modify it under either the terms of the
4
- {GPL2}[http://www.gnu.org/licenses/gpl-2.0.txt] (see link:COPYING) or
5
- the conditions below:
2
+ contributors, see the logs in revision control for all of them.
3
+
4
+ Bundled examples in the examples/ directory retain their respective
5
+ (Free Software) licenses. See copyright headers in individual files for
6
+ more information. This distribution only includes Free Software.
7
+
8
+ You can redistribute upr it and/or modify it under either the terms of
9
+ the {GPL2}[http://www.gnu.org/licenses/gpl-2.0.txt] (see link:COPYING)
10
+ or the conditions below:
6
11
 
7
12
  1. You may make and give away verbatim copies of the source form of the
8
13
  software without restriction, provided that you duplicate all of the
data/README CHANGED
@@ -1,15 +1,17 @@
1
1
  = upr - Upload Progress for Rack
2
2
 
3
3
  upr is Rack middleware that allows browser-side upload progress
4
- monitoring. It is based on the "mongrel_upload_progress" module, but
5
- allows any Moneta-backing store in additon to DRb. There is also a
6
- packaged example for using an ActiveRecord model for Rails.
4
+ monitoring. It is based on (and should be client-side compatible with)
5
+ several upload progress modules including ones used by leading web
6
+ servers. It allows any Moneta backing store in addition to DRb. There
7
+ is also a packaged example for using an ActiveRecord model for Rails.
7
8
 
8
9
  == Demo
9
10
 
10
- You can see upr it in action at http://upr-demo.bogomips.org/
11
- It will report the size and SHA1 of the file you've uploaded.
12
- Much of the demo was stolen from mongrel_upload_progress.
11
+ You can see upr in action at http://upr-demo.bogomips.org/ It will
12
+ report the size and SHA1 of the file you've uploaded. Much of the demo
13
+ was stolen from all the existing upload progress examples for other web
14
+ servers.
13
15
 
14
16
  == Web Server Compatibility
15
17
 
@@ -25,14 +27,27 @@ handful of concurrency models:
25
27
  For use with Revactor, the use of network-based Moneta stores or DRb is
26
28
  only advised if those stores are using Revactor-aware sockets.
27
29
 
28
- == JavaScript/HTML Compatibility
30
+ == JavaScript/CSS/HTML Compatibility
29
31
 
30
- The current developer does not react well with GUIs. Thus all (R)HTML
31
- and Prototype JavaScript code was stolen from mongrel_upload_progress.
32
+ The current developer does not react well with GUIs. Thus all (R)HTML,
33
+ JavaScript and CSS example code was stolen from one of the following:
32
34
 
33
- Contributions to add compatibility for more modern things like JQuery
34
- and HTML5 are very welcome.
35
+ 1. mongrel_upload_progress
36
+ http://mongrel.rubyforge.org/wiki/UploadProgress
37
+ 2. jquery-upload-progress
38
+ http://github.com/drogus/jquery-upload-progress
39
+ 3. mongrel_streaming_upload_progress
40
+ http://rubyforge.org/pipermail/mongrel-users/2007-July/003747.html
35
41
 
42
+ This means our module should also be compatible with any of these
43
+ interfaces.
44
+
45
+ Contributions to enhance compatibility for more modern things like
46
+ jQuery and HTML5 are very welcome. We would prefer as much as possible
47
+ to NOT proliferate new AJAX sub-protocols and use existing ones whenever
48
+ possible. Our current favorite is the Ajax.Pull JavaScript used in
49
+ Ry Dahl's mongrel_streaming_upload_progress because it only requires a
50
+ one extra HTTP request to pull all the status notifications.
36
51
 
37
52
  == Backend Compatibility
38
53
 
@@ -84,7 +99,8 @@ and we'll try our best to fix it.
84
99
 
85
100
  upr is copyright 2009 by all contributors (see logs in git). It is
86
101
  based on mongrel_upload_progress and carries the same license (Ruby +
87
- GPL2). See the included LICENSE file for details.
102
+ GPL2). Bundled examples may different Free Software licenses, see the
103
+ included LICENSE file for details.
88
104
 
89
105
  upr is 100% Free Software. We will never support the proliferation of
90
106
  non-Free browsers or plugins.
@@ -99,7 +115,7 @@ To subscribe or post to the mailing list, just send an email to
99
115
  upr@librelist.com and follow the instructions in the automated reply.
100
116
 
101
117
  * email: mailto:upr@librelist.com
102
- * git: git://git.bogomips.org/upr.git
118
+ * git: git://git.bogomips.org/upr.git or git://repo.or.cz/upr.git
103
119
  * cgit: http://git.bogomips.org/cgit/upr.git
104
120
 
105
121
  We will adhere to mostly the same conventions for patch submissions as
@@ -1,3 +1,10 @@
1
1
  class ApplicationController < ActionController::Base
2
- helper :all # include all helpers, all the time
2
+ # helper :all # include all helpers, all the time
3
+ defined?($upr) or before_filter do
4
+ # grab the backend in case we forget to set it (or if we're using DRb)
5
+ defined?($upr) or ObjectSpace.each_object(Upr::InputWrapper) do |x|
6
+ $upr ||= x.backend
7
+ end
8
+ end
9
+
3
10
  end
@@ -1,21 +1,27 @@
1
1
  require 'digest/sha1'
2
2
 
3
3
  class FilesController < ApplicationController
4
- defined?($upr) or before_filter do
5
- # grab the backend in case we forget to set it (or if we're using DRb)
6
- defined?($upr) or ObjectSpace.each_object(Upr::InputWrapper) do |x|
7
- $upr ||= x.backend
8
- end
4
+ # used by jQuery streaming upload progress
5
+ def new
6
+ _sha1_flash_self
7
+ end
8
+
9
+ # based on Ry Dahl's streaming AJAX pull:
10
+ # http://rubyforge.org/pipermail/mongrel-users/2007-July/003747.html
11
+ def pull
12
+ _sha1_flash_self
9
13
  end
10
14
 
11
15
  def index
12
16
  end
13
17
 
18
+ # used by mup-compatible upload progress
14
19
  def status
15
20
  tmp = $upr.read(params[:upload_id]).inspect
16
21
  render :text => "#{Rack::Utils.escape_html(tmp)}\n"
17
22
  end
18
23
 
24
+ # used by mup-compatible upload progress
19
25
  def progress
20
26
  render :update do |page|
21
27
  status = $upr.read(params[:upload_id]) and
@@ -23,19 +29,36 @@ class FilesController < ApplicationController
23
29
  end
24
30
  end
25
31
 
32
+ # used by mup-compatible upload progress
26
33
  def upload
27
- file = params[:data]
34
+ size, hexdigest = _read_sha1_size
35
+ render :text => "sha1: #{hexdigest}<br />" \
36
+ "size: #{size}<br />" \
37
+ '<script type="text/javascript">' \
38
+ 'window.parent.UploadProgress.finish();</script>'
39
+ end
40
+
41
+ private
42
+
43
+ def _read_sha1_size
44
+ file = params[:data] or return [ -1, :unknown ]
45
+ File.unlink(file.path) if file.respond_to?(:path)
28
46
  digest = Digest::SHA1.new
29
47
  if buf = file.read(16384)
30
48
  begin
31
49
  digest.update(buf)
32
50
  end while file.read(16384, buf)
33
51
  end
34
- size = file.stat.size
35
- File.unlink(file.path)
36
- render :text => "sha1: #{digest.hexdigest}<br />" \
37
- "size: #{size}<br />" \
38
- '<script type="text/javascript">' \
39
- 'window.parent.UploadProgress.finish();</script>'
52
+ [ file.size, digest.hexdigest ]
40
53
  end
54
+
55
+ def _sha1_flash_self
56
+ if request.post?
57
+ size, hexdigest = _read_sha1_size
58
+ msg = "Successfully upload file (size: #{size}, sha1: #{hexdigest})"
59
+ flash[:notice] = msg
60
+ redirect_to :action => params[:action]
61
+ end
62
+ end
63
+
41
64
  end
@@ -0,0 +1,11 @@
1
+ class ProgressController < ApplicationController
2
+ def index
3
+ opt = {
4
+ :backend => $upr,
5
+ :frequency => 0.5,
6
+ :env => request.env,
7
+ }
8
+ response.headers.update(Upr::JSON::RESPONSE_HEADERS)
9
+ render(Upr::JSON.new(opt).rails_render_options)
10
+ end
11
+ end
@@ -1,14 +1,8 @@
1
1
  class UprStatus < ActiveRecord::Base
2
- cattr_accessor :gc_cutoff
3
- @@gc_cutoff = 10
4
2
 
5
3
  class << self
6
4
  def read(upid)
7
- if rv = find_by_upid(upid)
8
- rv.time = Time.now.to_i
9
- rv.save
10
- rv
11
- end
5
+ find_by_upid(upid)
12
6
  end
13
7
 
14
8
  def start(upid, length)
@@ -22,14 +16,44 @@ class UprStatus < ActiveRecord::Base
22
16
  end
23
17
 
24
18
  def incr(upid, nr)
25
- update_all("seen = seen + #{nr.to_i}, time = #{Time.now.to_i}",
26
- { :upid => upid })
19
+ transaction do
20
+ if rv = find_by_upid(upid)
21
+ rv.time = Time.now.to_i
22
+ rv.seen += nr if rv.seen >= 0
23
+ rv.save
24
+ rv
25
+ end
26
+ end
27
+ end
28
+
29
+ def error!(upid)
30
+ transaction do
31
+ if rv = find_by_upid(upid)
32
+ rv.time = Time.now.to_i
33
+ rv.seen = -1
34
+ rv.save
35
+ rv
36
+ end
37
+ end
38
+ end
39
+
40
+ def finish(upid)
41
+ transaction do
42
+ if rv = find_by_upid(upid)
43
+ rv.time = Time.now.to_i
44
+ rv.length ||= rv.seen
45
+ rv.seen = rv.length
46
+ rv.save
47
+ rv
48
+ end
49
+ end
27
50
  end
28
51
 
29
52
  def gc
30
- cutoff = Time.now.to_i - @@gc_cutoff
53
+ cutoff = Time.now.to_i - Upr::Monitor::OPT[:expires_in]
31
54
  delete_all "time < #{cutoff}"
32
55
  end
33
56
  end
34
57
 
58
+ include Upr::StatusMethods
35
59
  end
@@ -2,7 +2,8 @@
2
2
  <head>
3
3
  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
4
4
  <title>upr test, http://upr.bogomips.org/</title>
5
- <%= javascript_include_tag :all %>
5
+ <%= javascript_include_tag :defaults %>
6
+ <%= javascript_include_tag 'upr' %>
6
7
  <style type="text/css">
7
8
  #progress-bar {
8
9
  width:500px;
@@ -42,9 +43,18 @@ opt = {
42
43
  }
43
44
  -%>
44
45
  <p>
45
- This is a demo of <a href="http://upr.bogomips.org/">upr</a> in action.
46
- Much of this (including all JS) was stolen from the mongrel_upload_progress
47
- examples.
46
+ This is a demo of <a href="http://upr.bogomips.org/">upr</a> in action.
47
+ Much of this (including all JS) was stolen from the mongrel_upload_progress
48
+ examples.
49
+ </p>
50
+ <p>
51
+ Also, see the <a href="/files/new">jQuery-compatible interface</a>
52
+ that's also compatible with upload progress modules for nginx and lighttpd.
53
+ </p>
54
+ <p>
55
+ Last but not least, check out the <a href="/files/pull">Ajax.Pull</a>
56
+ example that uses a single, streaming HTTP response to interatively
57
+ send progress updates.
48
58
  </p>
49
59
  <p><%= link_to upid, :action => 'status', :upload_id => upid %></p>
50
60
  <% form_tag(act, opt) do %>
@@ -0,0 +1,71 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <!-- example taken from git://github.com/drogus/jquery-upload-progress -->
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <title>ajaxFileUpload</title>
7
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
8
+ <script src="/javascripts/jquery.js"></script>
9
+ <script src="/javascripts/jquery.uploadProgress.js"></script>
10
+ <script type="text/javascript">
11
+ $(function() {
12
+ $('form').uploadProgress({
13
+ /* scripts locations for safari */
14
+ jqueryPath: "/javascripts/jquery.js",
15
+ uploadProgressPath: "/javascripts/jquery.uploadProgress.js",
16
+ start:function(){},
17
+ uploading: function(upload) {$('#percents').html(upload.percents+'%');},
18
+ interval: 500
19
+ });
20
+ });
21
+ </script>
22
+ <style type="text/css">
23
+ .bar {
24
+ width: 300px;
25
+ }
26
+
27
+ #progress {
28
+ background: #eee;
29
+ border: 1px solid #222;
30
+ margin-top: 20px;
31
+ }
32
+ #progressbar {
33
+ width: 0px;
34
+ height: 24px;
35
+ background: #333;
36
+ }
37
+ </style>
38
+ </head>
39
+
40
+ <body>
41
+ <% if flash[:notice] %>
42
+ <h1><%= flash[:notice] %></h1>
43
+ <% end %>
44
+ <p>
45
+ This is a demo of <a href="http://upr.bogomips.org/">upr</a> in action.
46
+ Much of this (including all JS) was stolen from the
47
+ <a href="http://github.com/drogus/jquery-upload-progress"
48
+ >jQuery-upload-progress</a>
49
+ </p>
50
+ <p>
51
+ Also, see the <a href="/">mongrel_upload_progress-compatible</a> version
52
+ </p>
53
+ <p>
54
+ Last but not least, check out the <a href="/files/pull">Ajax.Pull</a>
55
+ example that uses a single, streaming HTTP response to interatively
56
+ send progress updates.
57
+ </p>
58
+
59
+ <form id="upload" enctype="multipart/form-data" action="/files/new" method="post">
60
+ <input name="data" type="file"/>
61
+ <input type="submit" value="Upload"/>
62
+ </form>
63
+
64
+ <div id="uploading">
65
+ <div id="progress" class="bar">
66
+ <div id="progressbar">&nbsp;</div>
67
+ </div>
68
+ </div>
69
+ <div id="percents"></div>
70
+ </body>
71
+ </html>
@@ -0,0 +1,60 @@
1
+ <html>
2
+ <head>
3
+ <!-- http://rubyforge.org/pipermail/mongrel-users/2007-July/003747.html -->
4
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
5
+ <title>streaming upload progress test</title>
6
+ <%= javascript_include_tag 'ajax_pull/prototype-1_5_1.js' %>
7
+ <%= javascript_include_tag 'ajax_pull/ajax_pull.js' %>
8
+ <%= javascript_include_tag 'ajax_pull/upload_progress.js' %>
9
+ </head>
10
+ <body>
11
+ <%
12
+ upid = "#{Time.now.to_i}.#{rand}"
13
+ act = { :action => 'pull', :upload_id => upid }
14
+ opt = {
15
+ :multipart => true,
16
+ :target => 'upload-target',
17
+ :onsubmit => "UploadProgress.begin('#{upid}')"
18
+ }
19
+ -%>
20
+
21
+ <% if flash[:notice] %>
22
+ <div class="notice"><%= flash[:notice] %></div>
23
+ <% end %>
24
+ <p>
25
+ This is a demo of <a href="http://upr.bogomips.org/">upr</a> in action
26
+ with Ajax.Pull. It only uses a single, streaming AJAX request instead
27
+ of pulling. It is based on <a
28
+ href="http://rubyforge.org/pipermail/mongrel-users/2007-July/003747.html"
29
+ >mongrel_<b>streaming</b>_upload_progress</a>
30
+ </p>
31
+ <p>
32
+ This is different from the polling
33
+ <a href="/">mongrel_upload_progress-compatible</a> version
34
+ and also different from the polling
35
+ <a href="/files/new">jQuery+nginx/lighttpd-compatible</a> version
36
+ </p>
37
+
38
+ <p><%= link_to "#{upid} (single)",
39
+ :action => 'status', :upload_id => upid %></p>
40
+ <p><%= link_to "#{upid} (stream)",
41
+ "/progress?long&upload_id=#{upid}" %></p>
42
+
43
+ <% form_tag(act, opt) do %>
44
+ <div><p><%= file_field_tag :data %></p></div>
45
+ <p><%= submit_tag :Upload %></p>
46
+ <% end %>
47
+
48
+ <p>Below is the results <code>div</code></p>
49
+ <div id="results">(nothing)</div>
50
+
51
+ <p>Below is the progress bar <code>div</code></p>
52
+ <div id="progress-bar"></div>
53
+
54
+ <p>Below is the debug list</p>
55
+ <ol id="debug"></ol>
56
+
57
+ <iframe id="upload-target" name="upload-target" src="about:blank"></iframe>
58
+
59
+ </body>
60
+ </html>
@@ -1,3 +1,6 @@
1
1
  require 'config/environment'
2
+ use Rack::ContentLength
3
+ use Rack::Chunked
4
+ use Rack::Deflater
2
5
  use Rails::Rack::Static
3
6
  run ActionController::Dispatcher.new