diff --git a/lib/galaxy/datatypes/data.py b/lib/galaxy/datatypes/data.py index 9cf2cc1e429..524a7bd5f6c 100644 --- a/lib/galaxy/datatypes/data.py +++ b/lib/galaxy/datatypes/data.py @@ -261,84 +261,78 @@ class Data(metaclass=DataMeta): messagetype = "error" return error, msg, messagetype - def _archive_composite_dataset(self, trans, data=None, **kwd): + def _archive_composite_dataset(self, trans, data, do_action='zip'): # save a composite object into a compressed archive for downloading - params = util.Params(kwd) outfname = data.name[0:150] outfname = ''.join(c in FILENAME_VALID_CHARS and c or '_' for c in outfname) - if params.do_action is None: - params.do_action = 'zip' # default - msg = util.restore_text(params.get('msg', '')) - if not data: - msg = "You must select at least one dataset" - else: - error = False - try: - if params.do_action == 'zip': - # Can't use mkstemp - the file must not exist first - tmpd = tempfile.mkdtemp(dir=trans.app.config.new_file_path, prefix='gx_composite_archive_') - util.umask_fix_perms(tmpd, trans.app.config.umask, 0o777, trans.app.config.gid) - tmpf = os.path.join(tmpd, 'library_download.' + params.do_action) - archive = zipfile.ZipFile(tmpf, 'w', zipfile.ZIP_DEFLATED, True) + error = False + msg = '' + try: + if do_action == 'zip': + # Can't use mkstemp - the file must not exist first + tmpd = tempfile.mkdtemp(dir=trans.app.config.new_file_path, prefix='gx_composite_archive_') + util.umask_fix_perms(tmpd, trans.app.config.umask, 0o777, trans.app.config.gid) + tmpf = os.path.join(tmpd, 'library_download.' + do_action) + archive = zipfile.ZipFile(tmpf, 'w', zipfile.ZIP_DEFLATED, True) - def zipfile_add(fpath, arcname): - encoded_arcname = arcname.encode('CP437') - try: - archive.write(fpath, encoded_arcname) - except TypeError: - # Despite documenting the need for CP437 encoded arcname, - # python 3 actually needs this to be a unicode string ... - # https://bugs.python.org/issue24110 - archive.write(fpath, arcname) + def zipfile_add(fpath, arcname): + encoded_arcname = arcname.encode('CP437') + try: + archive.write(fpath, encoded_arcname) + except TypeError: + # Despite documenting the need for CP437 encoded arcname, + # python 3 actually needs this to be a unicode string ... + # https://bugs.python.org/issue24110 + archive.write(fpath, arcname) - archive.add = zipfile_add + archive.add = zipfile_add - elif params.do_action == 'tgz': - archive = util.streamball.StreamBall('w|gz') - elif params.do_action == 'tbz': - archive = util.streamball.StreamBall('w|bz2') - except (OSError, zipfile.BadZipFile): - error = True - log.exception("Unable to create archive for download") - msg = "Unable to create archive for %s for download, please report this error" % outfname + elif do_action == 'tgz': + archive = util.streamball.StreamBall('w|gz') + elif do_action == 'tbz': + archive = util.streamball.StreamBall('w|bz2') + except (OSError, zipfile.BadZipFile): + error = True + log.exception("Unable to create archive for download") + msg = "Unable to create archive for %s for download, please report this error" % outfname + if not error: + ext = data.extension + path = data.file_name + efp = data.extra_files_path + # Add any central file to the archive, + + display_name = os.path.splitext(outfname)[0] + if not display_name.endswith(ext): + display_name = '{}_{}'.format(display_name, ext) + + error, msg = self._archive_main_file(archive, display_name, path)[:2] if not error: - ext = data.extension - path = data.file_name - efp = data.extra_files_path - # Add any central file to the archive, - - display_name = os.path.splitext(outfname)[0] - if not display_name.endswith(ext): - display_name = '{}_{}'.format(display_name, ext) - - error, msg = self._archive_main_file(archive, display_name, path)[:2] - if not error: - # Add any child files to the archive, - for fpath, rpath in self.__archive_extra_files_path(extra_files_path=efp): - try: - archive.add(fpath, rpath) - except OSError: - error = True - log.exception("Unable to add %s to temporary library download archive", rpath) - msg = "Unable to create archive for download, please report this error" - continue - if not error: - if params.do_action == 'zip': - archive.close() - tmpfh = open(tmpf, 'rb') - # CANNOT clean up - unlink/rmdir was always failing because file handle retained to return - must rely on a cron job to clean up tmp - trans.response.set_content_type("application/x-zip-compressed") - trans.response.headers["Content-Disposition"] = 'attachment; filename="%s.zip"' % outfname - return tmpfh - else: - trans.response.set_content_type("application/x-tar") - outext = 'tgz' - if params.do_action == 'tbz': - outext = 'tbz' - trans.response.headers["Content-Disposition"] = 'attachment; filename="{}.{}"'.format(outfname, outext) - archive.wsgi_status = trans.response.wsgi_status() - archive.wsgi_headeritems = trans.response.wsgi_headeritems() - return archive.stream + # Add any child files to the archive, + for fpath, rpath in self.__archive_extra_files_path(extra_files_path=efp): + try: + archive.add(fpath, rpath) + except OSError: + error = True + log.exception("Unable to add %s to temporary library download archive", rpath) + msg = "Unable to create archive for download, please report this error" + continue + if not error: + if do_action == 'zip': + archive.close() + tmpfh = open(tmpf, 'rb') + # CANNOT clean up - unlink/rmdir was always failing because file handle retained to return - must rely on a cron job to clean up tmp + trans.response.set_content_type("application/x-zip-compressed") + trans.response.headers["Content-Disposition"] = 'attachment; filename="%s.zip"' % outfname + return tmpfh + else: + trans.response.set_content_type("application/x-tar") + outext = 'tgz' + if do_action == 'tbz': + outext = 'tbz' + trans.response.headers["Content-Disposition"] = 'attachment; filename="{}.{}"'.format(outfname, outext) + archive.wsgi_status = trans.response.wsgi_status() + archive.wsgi_headeritems = trans.response.wsgi_headeritems() + return archive.stream return trans.show_error_message(msg) def __archive_extra_files_path(self, extra_files_path): @@ -441,7 +435,7 @@ class Data(metaclass=DataMeta): from galaxy import datatypes # DBTODO REMOVE THIS AT REFACTOR if to_ext or isinstance(data.datatype, datatypes.binary.Binary): # Saving the file, or binary file if data.extension in composite_extensions: - return self._archive_composite_dataset(trans, data, **kwd) + return self._archive_composite_dataset(trans, data, do_action=kwd.get('do_action')) else: trans.response.headers['Content-Length'] = int(os.stat(data.file_name).st_size) filename = self._download_filename(data, to_ext, hdca=kwd.get("hdca", None), element_identifier=kwd.get("element_identifier", None))