upr 0.1.0 → 0.2.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.
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