Browse Source

Switched file upload and progress methods to expect nginx-style "X-Progress-ID" instead of "file_id" parameter.

Also updated example nginx config file to include directives for nginx's upload progress module.
Dan Helfman 9 years ago
parent
commit
4f3b478509
5 changed files with 37 additions and 19 deletions
  1. 2
    2
      INSTALL
  2. 17
    12
      controller/Files.py
  3. 7
    0
      controller/Validate.py
  4. 7
    0
      examples/nginx_luminotes
  5. 4
    5
      static/js/Wiki.js

+ 2
- 2
INSTALL View File

@@ -169,8 +169,8 @@ as per the example configuration file in examples/apache_luminotes.
169 169
 
170 170
 For nginx, if you want a working upload progress bar, build and install a
171 171
 version of nginx with the NginxHttpUploadProgressModule enabled. See:
172
-http://wiki.nginx.org//NginxHttpUploadProgressModule for more information.
173
-Then, configure nginx as per the example configuration file in
172
+http://github.com/masterzen/nginx-upload-progress-module/ for more
173
+information. Then, configure nginx as per the example configuration file in
174 174
 examples/nginx_luminotes.
175 175
 
176 176
 For either web server, you should change the paths in your configuration file

+ 17
- 12
controller/Files.py View File

@@ -133,7 +133,10 @@ class Upload_file( object ):
133 133
 
134 134
   @staticmethod
135 135
   def delete_file( file_id ):
136
-    return os.remove( Upload_file.make_server_filename( file_id ) )
136
+    try:
137
+      return os.remove( Upload_file.make_server_filename( file_id ) )
138
+    except OSError:
139
+      pass
137 140
 
138 141
   filename = property( lambda self: self.__filename )
139 142
 
@@ -174,7 +177,7 @@ class FieldStorage( cherrypy._cpcgifs.FieldStorage ):
174 177
     # pluck the file id out of the query string. it would be preferable to grab it out of parsed
175 178
     # form variables instead, but at this point in the processing, all the form variables might not
176 179
     # be parsed
177
-    file_id = cgi.parse_qs( cherrypy.request.query_string ).get( u"file_id", [ None ] )[ 0 ]
180
+    file_id = cgi.parse_qs( cherrypy.request.query_string ).get( u"X-Progress-ID", [ None ] )[ 0 ]
178 181
     try:
179 182
       file_id = Valid_id()( file_id )
180 183
     except ValueError:
@@ -549,13 +552,13 @@ class Files( object ):
549 552
     upload = (),
550 553
     notebook_id = Valid_id(),
551 554
     note_id = Valid_id( none_okay = True ),
552
-    file_id = Valid_id(),
555
+    x_progress_id = Valid_id(),
553 556
     user_id = Valid_id( none_okay = True ),
554 557
   )
555
-  def upload( self, upload, notebook_id, note_id, file_id, user_id ):
558
+  def upload( self, upload, notebook_id, note_id, x_progress_id, user_id ):
556 559
     """
557
-    Upload a file from the client for attachment to a particular note. The file_id must be provided
558
-    as part of the query string, even if the other values are submitted as form data.
560
+    Upload a file from the client for attachment to a particular note. The x_progress_id must be
561
+    provided as part of the query string, even if the other values are submitted as form data.
559 562
 
560 563
     @type upload: cgi.FieldStorage
561 564
     @param upload: file handle to uploaded file
@@ -563,8 +566,8 @@ class Files( object ):
563 566
     @param notebook_id: id of the notebook that the upload is to
564 567
     @type note_id: unicode or NoneType
565 568
     @param note_id: id of the note that the upload is to (if any)
566
-    @type file_id: unicode
567
-    @param file_id: id of the file being uploaded
569
+    @type x_progess_id: unicode
570
+    @param x_progess_id: id of the file being uploaded
568 571
     @type user_id: unicode or NoneType
569 572
     @param user_id: id of current logged-in user (if any)
570 573
     @rtype: unicode
@@ -573,6 +576,7 @@ class Files( object ):
573 576
     @raise Upload_error: the Content-Length header value is invalid
574 577
     """
575 578
     global current_uploads, current_uploads_lock
579
+    file_id = x_progress_id
576 580
 
577 581
     current_uploads_lock.acquire()
578 582
     try:
@@ -624,10 +628,10 @@ class Files( object ):
624 628
   @end_transaction
625 629
   @grab_user_id
626 630
   @validate(
627
-    file_id = Valid_id(),
631
+    x_progress_id = Valid_id(),
628 632
     user_id = Valid_id( none_okay = True ),
629 633
   )
630
-  def progress( self, file_id, user_id = None ):
634
+  def progress( self, x_progress_id, user_id = None ):
631 635
     """
632 636
     Return information on a file that is in the process of being uploaded. This method does not
633 637
     perform any access checks, but the only information revealed is the file's upload progress.
@@ -636,8 +640,8 @@ class Files( object ):
636 640
     intended to mimic the API described here:
637 641
     http://wiki.nginx.org//NginxHttpUploadProgressModule
638 642
 
639
-    @type file_id: unicode
640
-    @param file_id: id of a currently uploading file
643
+    @type x_progress_id: unicode
644
+    @param x_progress_id: id of a currently uploading file
641 645
     @type user_id: unicode or NoneType
642 646
     @param user_id: id of current logged-in user (if any)
643 647
     @rtype: dict
@@ -649,6 +653,7 @@ class Files( object ):
649 653
         'received': bytes_received, 'size': total_bytes }
650 654
     """
651 655
     global current_uploads
656
+    file_id = x_progress_id
652 657
 
653 658
     uploading_file = current_uploads.get( file_id )
654 659
     db_file = None

+ 7
- 0
controller/Validate.py View File

@@ -221,6 +221,13 @@ def validate( **expected ):
221 221
       args = list( args )
222 222
       args_index = 1 # skip the self argument
223 223
 
224
+      # make sure all kwarg names are lowercase and don't have dashes
225
+      for ( kwarg_name, value ) in kwargs.items():
226
+        new_kwarg_name = kwarg_name.replace( "-", "_" ).lower()
227
+        if new_kwarg_name != kwarg_name:
228
+          del( kwargs[ kwarg_name ] )
229
+          kwargs[ new_kwarg_name ] = value
230
+
224 231
       # determine the expected argument names from the decorated function itself
225 232
       code = function.func_code
226 233
       expected_names = code.co_varnames[ : code.co_argcount ]

+ 7
- 0
examples/nginx_luminotes View File

@@ -2,6 +2,8 @@ gzip_comp_level 4;
2 2
 gzip_min_length 1100;
3 3
 gzip_types text/plain text/html text/css application/x-javascript;
4 4
 
5
+upload_progress luminotes 1m;
6
+
5 7
 upstream luminotes {
6 8
   server 127.0.0.1:8081;
7 9
 }
@@ -15,6 +17,11 @@ server {
15 17
   location / {
16 18
     proxy_pass http://luminotes;
17 19
     client_max_body_size 505m;
20
+    track_uploads luminotes 30s;
21
+  }
22
+
23
+  location ^~ /files/progress {
24
+    report_uploads luminotes;
18 25
   }
19 26
 
20 27
   location /download/ {

+ 4
- 5
static/js/Wiki.js View File

@@ -3641,10 +3641,10 @@ function Upload_pulldown( wiki, notebook_id, invoker, editor, link, anchor, ephe
3641 3641
   appendChildNodes( this.upload_area, createDOM( "form",
3642 3642
     {
3643 3643
       "target": "upload_frame",
3644
-      "action": "/files/upload?file_id=new",
3644
+      "action": "/files/upload?X-Progress-ID=new&file_id=new",
3645 3645
       "method": "post",
3646 3646
       "enctype": "multipart/form-data",
3647
-      "id": "upload_form"
3647
+      "id": "upload_form",
3648 3648
     },
3649 3649
     createDOM( "span", { "class": "field_label" }, this.link ? "attach file: " : "import file: " ),
3650 3650
     createDOM( "input", { "name": "notebook_id", "id": "notebook_id", "type": "hidden", "value": notebook_id } ),
@@ -3681,7 +3681,7 @@ Upload_pulldown.prototype.update_file_id = function ( result ) {
3681 3681
 
3682 3682
   var upload_form = getElement( "upload_form" )
3683 3683
   if ( upload_form )
3684
-    upload_form.action = "/files/upload?file_id=" + this.file_id;
3684
+    upload_form.action = "/files/upload?X-Progress-ID=" + this.file_id;
3685 3685
 
3686 3686
   var file_id_node = getElement( "file_id" );
3687 3687
   if ( file_id_node )
@@ -3738,9 +3738,8 @@ Upload_pulldown.prototype.update_progress = function () {
3738 3738
   var self = this;
3739 3739
   var BAR_WIDTH_EM = 20.0;
3740 3740
 
3741
-  // TODO: send X- HTTP header nginx expects with file_id
3742 3741
   this.invoker.invoke( "/files/progress", "GET",
3743
-    { "file_id": this.file_id },
3742
+    { "X-Progress-ID": this.file_id },
3744 3743
     function( result ) {
3745 3744
       var fraction_done = 0.0;
3746 3745
       if ( !self.uploading )

Loading…
Cancel
Save