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.
This commit is contained in:
parent
92b7cf1084
commit
4f3b478509
4
INSTALL
4
INSTALL
|
@ -169,8 +169,8 @@ as per the example configuration file in examples/apache_luminotes.
|
||||||
|
|
||||||
For nginx, if you want a working upload progress bar, build and install a
|
For nginx, if you want a working upload progress bar, build and install a
|
||||||
version of nginx with the NginxHttpUploadProgressModule enabled. See:
|
version of nginx with the NginxHttpUploadProgressModule enabled. See:
|
||||||
http://wiki.nginx.org//NginxHttpUploadProgressModule for more information.
|
http://github.com/masterzen/nginx-upload-progress-module/ for more
|
||||||
Then, configure nginx as per the example configuration file in
|
information. Then, configure nginx as per the example configuration file in
|
||||||
examples/nginx_luminotes.
|
examples/nginx_luminotes.
|
||||||
|
|
||||||
For either web server, you should change the paths in your configuration file
|
For either web server, you should change the paths in your configuration file
|
||||||
|
|
|
@ -133,7 +133,10 @@ class Upload_file( object ):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_file( file_id ):
|
def delete_file( file_id ):
|
||||||
return os.remove( Upload_file.make_server_filename( file_id ) )
|
try:
|
||||||
|
return os.remove( Upload_file.make_server_filename( file_id ) )
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
filename = property( lambda self: self.__filename )
|
filename = property( lambda self: self.__filename )
|
||||||
|
|
||||||
|
@ -174,7 +177,7 @@ class FieldStorage( cherrypy._cpcgifs.FieldStorage ):
|
||||||
# pluck the file id out of the query string. it would be preferable to grab it out of parsed
|
# pluck the file id out of the query string. it would be preferable to grab it out of parsed
|
||||||
# form variables instead, but at this point in the processing, all the form variables might not
|
# form variables instead, but at this point in the processing, all the form variables might not
|
||||||
# be parsed
|
# be parsed
|
||||||
file_id = cgi.parse_qs( cherrypy.request.query_string ).get( u"file_id", [ None ] )[ 0 ]
|
file_id = cgi.parse_qs( cherrypy.request.query_string ).get( u"X-Progress-ID", [ None ] )[ 0 ]
|
||||||
try:
|
try:
|
||||||
file_id = Valid_id()( file_id )
|
file_id = Valid_id()( file_id )
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -549,13 +552,13 @@ class Files( object ):
|
||||||
upload = (),
|
upload = (),
|
||||||
notebook_id = Valid_id(),
|
notebook_id = Valid_id(),
|
||||||
note_id = Valid_id( none_okay = True ),
|
note_id = Valid_id( none_okay = True ),
|
||||||
file_id = Valid_id(),
|
x_progress_id = Valid_id(),
|
||||||
user_id = Valid_id( none_okay = True ),
|
user_id = Valid_id( none_okay = True ),
|
||||||
)
|
)
|
||||||
def upload( self, upload, notebook_id, note_id, file_id, user_id ):
|
def upload( self, upload, notebook_id, note_id, x_progress_id, user_id ):
|
||||||
"""
|
"""
|
||||||
Upload a file from the client for attachment to a particular note. The file_id must be provided
|
Upload a file from the client for attachment to a particular note. The x_progress_id must be
|
||||||
as part of the query string, even if the other values are submitted as form data.
|
provided as part of the query string, even if the other values are submitted as form data.
|
||||||
|
|
||||||
@type upload: cgi.FieldStorage
|
@type upload: cgi.FieldStorage
|
||||||
@param upload: file handle to uploaded file
|
@param upload: file handle to uploaded file
|
||||||
|
@ -563,8 +566,8 @@ class Files( object ):
|
||||||
@param notebook_id: id of the notebook that the upload is to
|
@param notebook_id: id of the notebook that the upload is to
|
||||||
@type note_id: unicode or NoneType
|
@type note_id: unicode or NoneType
|
||||||
@param note_id: id of the note that the upload is to (if any)
|
@param note_id: id of the note that the upload is to (if any)
|
||||||
@type file_id: unicode
|
@type x_progess_id: unicode
|
||||||
@param file_id: id of the file being uploaded
|
@param x_progess_id: id of the file being uploaded
|
||||||
@type user_id: unicode or NoneType
|
@type user_id: unicode or NoneType
|
||||||
@param user_id: id of current logged-in user (if any)
|
@param user_id: id of current logged-in user (if any)
|
||||||
@rtype: unicode
|
@rtype: unicode
|
||||||
|
@ -573,6 +576,7 @@ class Files( object ):
|
||||||
@raise Upload_error: the Content-Length header value is invalid
|
@raise Upload_error: the Content-Length header value is invalid
|
||||||
"""
|
"""
|
||||||
global current_uploads, current_uploads_lock
|
global current_uploads, current_uploads_lock
|
||||||
|
file_id = x_progress_id
|
||||||
|
|
||||||
current_uploads_lock.acquire()
|
current_uploads_lock.acquire()
|
||||||
try:
|
try:
|
||||||
|
@ -624,10 +628,10 @@ class Files( object ):
|
||||||
@end_transaction
|
@end_transaction
|
||||||
@grab_user_id
|
@grab_user_id
|
||||||
@validate(
|
@validate(
|
||||||
file_id = Valid_id(),
|
x_progress_id = Valid_id(),
|
||||||
user_id = Valid_id( none_okay = True ),
|
user_id = Valid_id( none_okay = True ),
|
||||||
)
|
)
|
||||||
def progress( self, file_id, user_id = None ):
|
def progress( self, x_progress_id, user_id = None ):
|
||||||
"""
|
"""
|
||||||
Return information on a file that is in the process of being uploaded. This method does not
|
Return information on a file that is in the process of being uploaded. This method does not
|
||||||
perform any access checks, but the only information revealed is the file's upload progress.
|
perform any access checks, but the only information revealed is the file's upload progress.
|
||||||
|
@ -636,8 +640,8 @@ class Files( object ):
|
||||||
intended to mimic the API described here:
|
intended to mimic the API described here:
|
||||||
http://wiki.nginx.org//NginxHttpUploadProgressModule
|
http://wiki.nginx.org//NginxHttpUploadProgressModule
|
||||||
|
|
||||||
@type file_id: unicode
|
@type x_progress_id: unicode
|
||||||
@param file_id: id of a currently uploading file
|
@param x_progress_id: id of a currently uploading file
|
||||||
@type user_id: unicode or NoneType
|
@type user_id: unicode or NoneType
|
||||||
@param user_id: id of current logged-in user (if any)
|
@param user_id: id of current logged-in user (if any)
|
||||||
@rtype: dict
|
@rtype: dict
|
||||||
|
@ -649,6 +653,7 @@ class Files( object ):
|
||||||
'received': bytes_received, 'size': total_bytes }
|
'received': bytes_received, 'size': total_bytes }
|
||||||
"""
|
"""
|
||||||
global current_uploads
|
global current_uploads
|
||||||
|
file_id = x_progress_id
|
||||||
|
|
||||||
uploading_file = current_uploads.get( file_id )
|
uploading_file = current_uploads.get( file_id )
|
||||||
db_file = None
|
db_file = None
|
||||||
|
|
|
@ -221,6 +221,13 @@ def validate( **expected ):
|
||||||
args = list( args )
|
args = list( args )
|
||||||
args_index = 1 # skip the self argument
|
args_index = 1 # skip the self argument
|
||||||
|
|
||||||
|
# make sure all kwarg names are lowercase and don't have dashes
|
||||||
|
for ( kwarg_name, value ) in kwargs.items():
|
||||||
|
new_kwarg_name = kwarg_name.replace( "-", "_" ).lower()
|
||||||
|
if new_kwarg_name != kwarg_name:
|
||||||
|
del( kwargs[ kwarg_name ] )
|
||||||
|
kwargs[ new_kwarg_name ] = value
|
||||||
|
|
||||||
# determine the expected argument names from the decorated function itself
|
# determine the expected argument names from the decorated function itself
|
||||||
code = function.func_code
|
code = function.func_code
|
||||||
expected_names = code.co_varnames[ : code.co_argcount ]
|
expected_names = code.co_varnames[ : code.co_argcount ]
|
||||||
|
|
|
@ -2,6 +2,8 @@ gzip_comp_level 4;
|
||||||
gzip_min_length 1100;
|
gzip_min_length 1100;
|
||||||
gzip_types text/plain text/html text/css application/x-javascript;
|
gzip_types text/plain text/html text/css application/x-javascript;
|
||||||
|
|
||||||
|
upload_progress luminotes 1m;
|
||||||
|
|
||||||
upstream luminotes {
|
upstream luminotes {
|
||||||
server 127.0.0.1:8081;
|
server 127.0.0.1:8081;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +17,11 @@ server {
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://luminotes;
|
proxy_pass http://luminotes;
|
||||||
client_max_body_size 505m;
|
client_max_body_size 505m;
|
||||||
|
track_uploads luminotes 30s;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /files/progress {
|
||||||
|
report_uploads luminotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /download/ {
|
location /download/ {
|
||||||
|
|
|
@ -3641,10 +3641,10 @@ function Upload_pulldown( wiki, notebook_id, invoker, editor, link, anchor, ephe
|
||||||
appendChildNodes( this.upload_area, createDOM( "form",
|
appendChildNodes( this.upload_area, createDOM( "form",
|
||||||
{
|
{
|
||||||
"target": "upload_frame",
|
"target": "upload_frame",
|
||||||
"action": "/files/upload?file_id=new",
|
"action": "/files/upload?X-Progress-ID=new&file_id=new",
|
||||||
"method": "post",
|
"method": "post",
|
||||||
"enctype": "multipart/form-data",
|
"enctype": "multipart/form-data",
|
||||||
"id": "upload_form"
|
"id": "upload_form",
|
||||||
},
|
},
|
||||||
createDOM( "span", { "class": "field_label" }, this.link ? "attach file: " : "import file: " ),
|
createDOM( "span", { "class": "field_label" }, this.link ? "attach file: " : "import file: " ),
|
||||||
createDOM( "input", { "name": "notebook_id", "id": "notebook_id", "type": "hidden", "value": notebook_id } ),
|
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 ) {
|
||||||
|
|
||||||
var upload_form = getElement( "upload_form" )
|
var upload_form = getElement( "upload_form" )
|
||||||
if ( upload_form )
|
if ( upload_form )
|
||||||
upload_form.action = "/files/upload?file_id=" + this.file_id;
|
upload_form.action = "/files/upload?X-Progress-ID=" + this.file_id;
|
||||||
|
|
||||||
var file_id_node = getElement( "file_id" );
|
var file_id_node = getElement( "file_id" );
|
||||||
if ( file_id_node )
|
if ( file_id_node )
|
||||||
|
@ -3738,9 +3738,8 @@ Upload_pulldown.prototype.update_progress = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
var BAR_WIDTH_EM = 20.0;
|
var BAR_WIDTH_EM = 20.0;
|
||||||
|
|
||||||
// TODO: send X- HTTP header nginx expects with file_id
|
|
||||||
this.invoker.invoke( "/files/progress", "GET",
|
this.invoker.invoke( "/files/progress", "GET",
|
||||||
{ "file_id": this.file_id },
|
{ "X-Progress-ID": this.file_id },
|
||||||
function( result ) {
|
function( result ) {
|
||||||
var fraction_done = 0.0;
|
var fraction_done = 0.0;
|
||||||
if ( !self.uploading )
|
if ( !self.uploading )
|
||||||
|
|
Reference in New Issue