mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #10330 from mvdbeek/fix_download_of_composite_data_from_collections
[20.09] Fix composite data download from collection
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user