witten
/
luminotes
Archived
1
0
Fork 0

Rewrote controller.Files.upload_file() not to use a CherryPy-2.1-style file upload filter.

Now releasing session lock before streaming the file to prevent session deadlock in the event of a cancelled upload.
This commit is contained in:
Dan Helfman 2008-02-04 20:06:02 +00:00
parent 362a125b1b
commit 04f86f05a6
4 changed files with 20 additions and 26 deletions

View File

@ -1,4 +1,5 @@
import cherrypy
import types
# module-level variable that, when set to a view, overrides the view for all exposed methods. used
# by unit tests
@ -64,7 +65,7 @@ def expose( view = None, rss = None ):
result = dict( error = u"An error occurred when processing your request. Please try again or contact support." )
# if the result is a generator, it's streaming data, so just let CherryPy handle it
if hasattr( result, "gi_running" ):
if isinstance( result, types.GeneratorType ):
return result
redirect = result.get( u"redirect", None )

View File

@ -1,6 +1,5 @@
import cgi
import cherrypy
from cherrypy.filters import basefilter
from Expose import expose
from Validate import validate
from Database import Valid_id
@ -37,21 +36,7 @@ class Upload_error( Exception ):
)
class File_upload_filter( basefilter.BaseFilter ):
def before_request_body( self ):
if cherrypy.request.path != "/files/upload_file":
return
if cherrypy.request.method != "POST":
raise Upload_error()
# tell CherryPy not to parse the POST data itself for this URL
cherrypy.request.processRequestBody = False
class Files( object ):
_cpFilterList = [ File_upload_filter() ]
"""
Controller for dealing with uploaded files, corresponding to the "/files" URL.
"""
@ -94,20 +79,31 @@ class Files( object ):
@strongly_expire
@grab_user_id
@validate(
upload = (),
notebook_id = Valid_id(),
note_id = Valid_id(),
user_id = Valid_id( none_okay = True ),
)
def upload_file( self, user_id ):
def upload_file( self, upload, notebook_id, note_id, user_id ):
"""
Upload a file from the client for attachment to a particular note.
@type upload: cgi.FieldStorage
@param upload: file handle to uploaded file
@type notebook_id: unicode
@param notebook_id: id of the notebook that the upload is to
@type note_id: unicode
@param note_id: id of the note that the upload is to
@raise Access_error: the current user doesn't have access to the given notebook or note
@raise Upload_error: an error occurred when processing the uploaded file
@type user_id: unicode or NoneType
@param user_id: id of current logged-in user (if any)
@rtype: unicode
@return: rendered HTML page
"""
if not self.__users.check_access( user_id, notebook_id ):
raise Access_error()
cherrypy.server.max_request_body_size = 0 # remove file size limit of 100 MB
cherrypy.response.timeout = 3600 # increase upload timeout to one hour (default is 5 min)
cherrypy.server.socket_timeout = 60 # increase socket timeout to one minute (default is 10 sec)
@ -125,15 +121,8 @@ class Files( object ):
if file_size <= 0:
raise Upload_error()
parsed_form = cgi.FieldStorage( fp = cherrypy.request.rfile, headers = headers, environ = { "REQUEST_METHOD": "POST" }, keep_blank_values = 1)
upload = parsed_form[ u"file" ]
notebook_id = parsed_form.getvalue( u"notebook_id" )
note_id = parsed_form.getvalue( u"note_id" )
filename = upload.filename.strip()
if not self.__users.check_access( user_id, notebook_id ):
raise Access_error()
def process_upload():
"""
Process the file upload while streaming a progress meter as it uploads.
@ -222,4 +211,8 @@ class Files( object ):
upload.file.close()
cherrypy.request.rfile.close()
# release the session lock before beginning the upload, because if the upload is cancelled
# before it's done, the lock won't be released
cherrypy.session.release_lock()
return process_upload()

View File

@ -2258,7 +2258,7 @@ Upload_pulldown.prototype.init_frame = function () {
withDocument( doc, function () {
connect( "upload_button", "onclick", function ( event ) {
withDocument( doc, function () {
self.upload_started( getElement( "file" ).value );
self.upload_started( getElement( "upload" ).value );
} );
} );
} );

View File

@ -12,7 +12,7 @@ class Upload_page( Html ):
Body(
Form(
Span( u"attach file: ", class_ = u"field_label" ),
Input( type = u"file", id = u"file", name = u"file", class_ = "text_field", size = u"30" ),
Input( type = u"file", id = u"upload", name = u"upload", class_ = "text_field", size = u"30" ),
Input( type = u"submit", id = u"upload_button", class_ = u"button", value = u"upload" ),
Input( type = u"hidden", id = u"notebook_id", name = u"notebook_id", value = notebook_id ),
Input( type = u"hidden", id = u"note_id", name = u"note_id", value = note_id ),