Rev3464, Download site as zip
This commit is contained in:
parent
1ae84c11ad
commit
e874730679
3 changed files with 76 additions and 2 deletions
|
@ -17,6 +17,7 @@ from Plugin import PluginManager
|
||||||
from Debug import Debug
|
from Debug import Debug
|
||||||
from Translate import Translate
|
from Translate import Translate
|
||||||
from util import helper
|
from util import helper
|
||||||
|
from ZipStream import ZipStream
|
||||||
|
|
||||||
plugin_dir = "plugins/Sidebar"
|
plugin_dir = "plugins/Sidebar"
|
||||||
media_dir = plugin_dir + "/media"
|
media_dir = plugin_dir + "/media"
|
||||||
|
@ -62,6 +63,28 @@ class UiRequestPlugin(object):
|
||||||
for part in super(UiRequestPlugin, self).actionUiMedia(path):
|
for part in super(UiRequestPlugin, self).actionUiMedia(path):
|
||||||
yield part
|
yield part
|
||||||
|
|
||||||
|
def actionZip(self):
|
||||||
|
address = self.get["address"]
|
||||||
|
site = self.server.site_manager.get(address)
|
||||||
|
if not site:
|
||||||
|
return self.error404("Site not found")
|
||||||
|
|
||||||
|
title = site.content_manager.contents.get("content.json", {}).get("title", "").encode('ascii', 'ignore')
|
||||||
|
filename = "%s-backup-%s.zip" % (title, time.strftime("%Y-%m-%d_%H_%M"))
|
||||||
|
self.sendHeader(content_type="application/zip", extra_headers={'Content-Disposition': 'attachment; filename="%s"' % filename})
|
||||||
|
|
||||||
|
return self.streamZip(site.storage.getPath("."))
|
||||||
|
|
||||||
|
def streamZip(self, file_path):
|
||||||
|
zs = ZipStream(file_path)
|
||||||
|
while 1:
|
||||||
|
data = zs.read()
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
yield data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@PluginManager.registerTo("UiWebsocket")
|
@PluginManager.registerTo("UiWebsocket")
|
||||||
class UiWebsocketPlugin(object):
|
class UiWebsocketPlugin(object):
|
||||||
|
@ -137,7 +160,15 @@ class UiWebsocketPlugin(object):
|
||||||
"""))
|
"""))
|
||||||
|
|
||||||
def sidebarRenderFileStats(self, body, site):
|
def sidebarRenderFileStats(self, body, site):
|
||||||
body.append(_(u"<li><label>{_[Files]} <small><a href='#Site+directory' id='link-directory' class='link-right'>{_[Open site directory]}</a></small></label><ul class='graph graph-stacked'>"))
|
body.append(_(u"""
|
||||||
|
<li>
|
||||||
|
<label>
|
||||||
|
{_[Files]}
|
||||||
|
<small><a href='#Site+directory' id='link-directory' class='link-right'>{_[Open site directory]}</a>
|
||||||
|
<a href='/ZeroNet-Internal/Zip?address={site.address}' id='link-zip' class='link-right'>{_[Download as .zip]}</a></small>
|
||||||
|
</label>
|
||||||
|
<ul class='graph graph-stacked'>
|
||||||
|
"""))
|
||||||
|
|
||||||
extensions = (
|
extensions = (
|
||||||
("html", "yellow"),
|
("html", "yellow"),
|
||||||
|
|
43
plugins/Sidebar/ZipStream.py
Normal file
43
plugins/Sidebar/ZipStream.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import cStringIO as StringIO
|
||||||
|
import os
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
|
||||||
|
class ZipStream(file):
|
||||||
|
def __init__(self, dir_path):
|
||||||
|
self.dir_path = dir_path
|
||||||
|
self.pos = 0
|
||||||
|
self.zf = zipfile.ZipFile(self, 'w', zipfile.ZIP_DEFLATED)
|
||||||
|
self.buff = StringIO.StringIO()
|
||||||
|
self.file_list = self.getFileList()
|
||||||
|
|
||||||
|
def getFileList(self):
|
||||||
|
for root, dirs, files in os.walk(self.dir_path):
|
||||||
|
for file in files:
|
||||||
|
file_path = root + "/" + file
|
||||||
|
relative_path = os.path.join(os.path.relpath(root, self.dir_path), file)
|
||||||
|
yield file_path, relative_path
|
||||||
|
self.zf.close()
|
||||||
|
|
||||||
|
def read(self, size=60 * 1024):
|
||||||
|
for file_path, relative_path in self.file_list:
|
||||||
|
self.zf.write(file_path, relative_path)
|
||||||
|
if self.buff.tell() >= size:
|
||||||
|
break
|
||||||
|
self.buff.seek(0)
|
||||||
|
back = self.buff.read()
|
||||||
|
self.buff.truncate(0)
|
||||||
|
return back
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
self.pos += len(data)
|
||||||
|
self.buff.write(data)
|
||||||
|
|
||||||
|
def tell(self):
|
||||||
|
return self.pos
|
||||||
|
|
||||||
|
def seek(self, pos, type):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
|
@ -10,7 +10,7 @@ class Config(object):
|
||||||
|
|
||||||
def __init__(self, argv):
|
def __init__(self, argv):
|
||||||
self.version = "0.6.2"
|
self.version = "0.6.2"
|
||||||
self.rev = 3465
|
self.rev = 3467
|
||||||
self.argv = argv
|
self.argv = argv
|
||||||
self.action = None
|
self.action = None
|
||||||
self.config_file = "zeronet.conf"
|
self.config_file = "zeronet.conf"
|
||||||
|
|
Loading…
Reference in a new issue