details: http://www.bx.psu.edu/hg/galaxy/rev/37ecd71e87f3 changeset: 3813:37ecd71e87f3 user: Nate Coraor <nate@bx.psu.edu> date: Mon May 24 14:46:19 2010 -0400 description: Added nginx mod_zip support for library downloads diffstat: lib/galaxy/config.py | 1 + lib/galaxy/web/controllers/library_common.py | 40 ++++++++++++++++++++++----- templates/library/common/common.mako | 8 +++++ 3 files changed, 41 insertions(+), 8 deletions(-) diffs (144 lines): diff -r 663b2fd4a44c -r 37ecd71e87f3 lib/galaxy/config.py --- a/lib/galaxy/config.py Mon May 24 14:15:02 2010 -0400 +++ b/lib/galaxy/config.py Mon May 24 14:46:19 2010 -0400 @@ -101,6 +101,7 @@ # Configuration options for taking advantage of nginx features self.apache_xsendfile = kwargs.get( 'apache_xsendfile', False ) self.nginx_x_accel_redirect_base = kwargs.get( 'nginx_x_accel_redirect_base', False ) + self.nginx_x_archive_files_base = kwargs.get( 'nginx_x_archive_files_base', False ) self.nginx_upload_store = kwargs.get( 'nginx_upload_store', False ) self.nginx_upload_path = kwargs.get( 'nginx_upload_path', False ) if self.nginx_upload_store: diff -r 663b2fd4a44c -r 37ecd71e87f3 lib/galaxy/web/controllers/library_common.py --- a/lib/galaxy/web/controllers/library_common.py Mon May 24 14:15:02 2010 -0400 +++ b/lib/galaxy/web/controllers/library_common.py Mon May 24 14:46:19 2010 -0400 @@ -106,6 +106,9 @@ message += "Don't navigate away from Galaxy or use the browser's \"stop\" or \"reload\" buttons (on this tab) until the " message += "message \"This job is running\" is cleared from the \"Information\" column below for each selected dataset." status = "info" + comptypes_t = comptypes + if trans.app.config.nginx_x_archive_files_base: + comptypes_t = ['ngxzip'] return trans.fill_template( '/library/common/browse_library.mako', cntrller=cntrller, use_panels=use_panels, @@ -113,7 +116,7 @@ created_ldda_ids=created_ldda_ids, hidden_folder_ids=hidden_folder_ids, show_deleted=show_deleted, - comptypes=comptypes, + comptypes=comptypes_t, current_user_roles=current_user_roles, message=message, status=status ) @@ -1253,6 +1256,19 @@ status=status ) @web.expose def act_on_multiple_datasets( self, trans, cntrller, library_id, ldda_ids='', **kwd ): + class NgxZip( object ): + def __init__( self, url_base ): + self.files = {} + self.url_base = url_base + def add( self, file, relpath ): + self.files[file] = relpath + def __str__( self ): + rval = '' + for fname, relpath in self.files.items(): + size = os.stat( fname ).st_size + quoted_fname = urllib.quote_plus( fname, '/' ) + rval += '- %i %s%s %s\n' % ( size, self.url_base, quoted_fname, relpath ) + return rval # Perform an action on a list of library datasets. params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) @@ -1319,10 +1335,10 @@ trans.sa_session.add( ld ) trans.sa_session.flush() message = "The selected datasets have been removed from this data library" - elif action in ['zip','tgz','tbz']: + elif action in ['zip','tgz','tbz','ngxzip']: error = False killme = string.punctuation + string.whitespace - trantab = string.maketrans(killme,'_'*len(killme)) + trantab = string.maketrans(killme,'_'*len(killme)) try: outext = 'zip' if action == 'zip': @@ -1340,6 +1356,8 @@ elif action == 'tbz': archive = util.streamball.StreamBall( 'w|bz2' ) outext = 'tbz2' + elif action == 'ngxzip': + archive = NgxZip( trans.app.config.nginx_x_archive_files_base ) except (OSError, zipfile.BadZipFile): error = True log.exception( "Unable to create archive for download" ) @@ -1347,7 +1365,7 @@ status = 'error' except: error = True - log.exception( "Unexpected error %s in create archive for download" % sys.exc_info()[0]) + log.exception( "Unexpected error %s in create archive for download" % sys.exc_info()[0]) message = "Unable to create archive for download, please report - %s" % sys.exc_info()[0] status = 'error' if not error: @@ -1377,7 +1395,8 @@ seen.append( path ) zpath = os.path.split(path)[-1] # comes as base_name/fname outfname,zpathext = os.path.splitext(zpath) - if is_composite: # need to add all the components from the extra_files_path to the zip + if is_composite: + # need to add all the components from the extra_files_path to the zip if zpathext == '': zpath = '%s.html' % zpath # fake the real nature of the html file try: @@ -1391,8 +1410,8 @@ flist = glob.glob(os.path.join(ldda.dataset.extra_files_path,'*.*')) # glob returns full paths for fpath in flist: efp,fname = os.path.split(fpath) - if fname > '': - fname = fname.translate(trantab) + if fname > '': + fname = fname.translate(trantab) try: archive.add( fpath,fname ) except IOError: @@ -1409,7 +1428,7 @@ log.exception( "Unable to write %s to temporary library download archive" % ldda.dataset.file_name) message = "Unable to create archive for download, please report this error" status = 'error' - if not error: + if not error: if action == 'zip': archive.close() tmpfh = open( tmpf ) @@ -1426,6 +1445,11 @@ trans.response.set_content_type( "application/x-zip-compressed" ) trans.response.headers[ "Content-Disposition" ] = "attachment; filename=%s.%s" % (outfname,outext) return tmpfh + elif action == 'ngxzip': + #trans.response.set_content_type( "application/x-zip-compressed" ) + #trans.response.headers[ "Content-Disposition" ] = "attachment; filename=%s.%s" % (outfname,outext) + trans.response.headers[ "X-Archive-Files" ] = "zip" + return archive else: trans.response.set_content_type( "application/x-tar" ) trans.response.headers[ "Content-Disposition" ] = "attachment; filename=%s.%s" % (outfname,outext) diff -r 663b2fd4a44c -r 37ecd71e87f3 templates/library/common/common.mako --- a/templates/library/common/common.mako Mon May 24 14:15:02 2010 -0400 +++ b/templates/library/common/common.mako Mon May 24 14:46:19 2010 -0400 @@ -391,6 +391,14 @@ %if 'zip' in comptypes: <option value="zip">Download as a .zip file</option> %endif + %if 'ngxzip' in comptypes: + ## We can safely have two default selected items since ngxzip, if present, will always be the only available type. + <option value="ngxzip" + %if default_action == 'download': + selected + %endif> + >Download as a .zip file</option> + %endif %endif </select> <input type="submit" class="primary-button" name="action_on_datasets_button" id="action_on_datasets_button" value="Go"/>