Commit b7d7a2d5 authored by Fabian-Andree Heidemann's avatar Fabian-Andree Heidemann
Browse files

[file] extend compress/download of multiple files or folder by tempfile...

[file] extend compress/download of multiple files or folder by tempfile archive with automatic clean-up
parent 39a550d7
......@@ -23,7 +23,7 @@ class FSController(AbstractController):
AbstractController.__init__(self, mount_static=False)
@staticmethod
def _stream_remote_file(fs, path):
def _stream_remote_file(fs, path, callback=None):
offset = 0
buffer_size = 2 ** 20
while True:
......@@ -41,10 +41,17 @@ class FSController(AbstractController):
yield data
if hasattr(callback, "__call__"):
callback()
@cherrypy.expose
@cherrypy.tools.ajax(on=False)
@cherrypy.tools.method(accept="GET")
def getfile(self, path, download=None, **kwargs):
def getfile(self, path, download=None, deleteoncomplete=None, **kwargs):
truthy = ("true", "1", "yes")
deleteoncomplete = deleteoncomplete and deleteoncomplete.lower() in truthy
download = download and download.lower() in truthy
fs = self.get('fs')
stats = fs.stat(path)
if not stat.S_ISREG(stats.st_mode):
......@@ -61,7 +68,7 @@ class FSController(AbstractController):
headers['Content-Length'] = stats.st_size
cptools.validate_since()
if download and download.lower() in ['true', '1', 'yes']:
if download:
disposition = 'attachment; filename=%s' % path.split('/')[-1]
else:
disposition = 'inline; filename=%s' % path.split('/')[-1]
......@@ -75,7 +82,12 @@ class FSController(AbstractController):
self.release()
return FSController._stream_remote_file(fs, path)
callback = None
if deleteoncomplete:
def callback():
fs.remove(path)
return FSController._stream_remote_file(fs, path, callback)
getfile._cp_config = {'response.stream': True}
......@@ -209,7 +221,10 @@ class FSAjaxController(AbstractController):
@cherrypy.expose
@cherrypy.tools.method(accept="POST")
def compress(self, path, paths, name):
def compress(self, paths, path, name="", isTmp=False):
isTmp = isTmp and isTmp.lower() in ("true", "1", "yes")
if not isTmp and not name:
raise AjaxException("Either name or isTmp must be given.")
self.release_session()
fs = self.get('fs')
self.release_database()
......@@ -217,7 +232,7 @@ class FSAjaxController(AbstractController):
# so convert it with the convert function
paths = json.loads(paths)
try:
fs.compress(path, paths, name)
return fs.compress(paths, path, name, isTmp)
except Exception as e:
raise AjaxException(str(e).split("\n")[0])
......
......@@ -402,44 +402,45 @@ define([
var self = this;
var path = Object.keys(this.FileBase.selections.entries);
function _download(path) {
function _download(path, deleteOnComplete) {
$("<iframe />")
.attr({
src: vispa.url.dynamic("fs/getfile/?path=" + path +
src: vispa.url.dynamic("fs/getfile/?" +
"path=" + path +
"&_workspaceId=" + String(self.FileBase.instance.getWorkspaceId()) +
"&download=1"),
"&download=1" +
"&deleteoncomplete=" + String(deleteOnComplete)),
style: "display:none;"
}).appendTo("body");
}
if (path.length != 1) {
var archive = "/tmp/" + vispa.uuid(16)
self.compress(archive, function () {
_download(archive + ".zip");
});
self.compress(undefined, function (err, archive) {
_download(archive, true);
}, true);
} else if (path.length == 1 && self.FileBase.selections.entries[
Object.keys(self.FileBase.selections.entries)].data().data.type == "d") {
var archive = "/tmp/" + self.FileBase.helper.filenameFromPath(path[0])
self.compress(archive, function () {
_download(archive + ".zip");
});
self.compress(undefined, function (err, archive) {
_download(archive, true);
}, true);
} else {
_download(path[0]);
}
},
compress: function (name, callback) {
compress: function (name, callback, isTmp) {
var self = this;
function _compress(name) {
self.FileBase.instance.POST("/ajax/fs/compress", {
path: self.FileBase.instance.getState("path"),
paths: JSON.stringify(Object.keys(self.FileBase.selections.entries)),
name: name
path: self.FileBase.instance.getState("path"),
name: name,
isTmp: isTmp
}, callback);
}
if (name) {
if (name || isTmp) {
_compress(name);
} else {
self.FileBase.instance.prompt("Enter a name for the zip-file", function (newName) {
......
......@@ -18,6 +18,7 @@ import stat
import subprocess
import fsmonitor
import vispa
import tempfile
try:
import Image
......@@ -315,18 +316,21 @@ class FileSystem(object):
os.remove(source)
def compress(self, path, paths, name):
def compress(self, paths, path, name, is_tmp=False):
# paths has to be a list of strings
paths = paths if isinstance(paths, (list, tuple)) else [paths]
paths = [self.expand(p) for p in paths]
path = path if not path.endswith(os.sep) else path[:-1]
path = self.expand(path)
name = name if name.endswith(".zip") else name + ".zip"
name = self.handle_file_name_collision(name, path)
if is_tmp:
fullpath = os.path.join(tempfile._get_default_tempdir(),
next(tempfile._get_candidate_names()) + ".zip")
else:
path = path if not path.endswith(os.sep) else path[:-1]
path = self.expand(path)
name = name if name.endswith(".zip") else name + ".zip"
name = self.handle_file_name_collision(name, path)
fullpath = os.path.join(path, name)
fullpath = os.path.join(path, name)
with ZipFile(fullpath, "w") as archive:
i = 0
......@@ -352,6 +356,8 @@ class FileSystem(object):
logger.debug(p)
archive.write(p, ap)
return fullpath
def decompress(self, path):
# filepath and extract path
path = self.expand(path)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment