Skip to content

Instantly share code, notes, and snippets.

@cdw9
Last active January 22, 2021 09:07
Show Gist options
  • Save cdw9/b61200b5a218f2711874e03523c94cbc to your computer and use it in GitHub Desktop.
Save cdw9/b61200b5a218f2711874e03523c94cbc to your computer and use it in GitHub Desktop.
Plone batch file download - adds a download link to folders, will create a .zip of all files or PDFs in the folder
...
<browser:page
name="download_files"
for="plone.app.contenttypes.interfaces.IFolder"
permission="cmf.ModifyPortalContent"
class=".folders.DownloadFiles"
/>
...
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="plone">
<body>
<metal:block fill-slot="top_slot"
tal:define="disable_column_one python:request.set('disable_plone.leftcolumn',1);
disable_column_two python:request.set('disable_plone.rightcolumn',1);" />
<metal:content-core fill-slot="content-core">
<p>Submit the form below to download a .zip of files contained in this folder.</p>
<p>This process may take a while.
If the request times out, the zip file will still be created in this folder.
Check for the new file in
<a href="${context/absolute_url}/folder_contents">folder contents</a>.</p>
<form action="">
<label for="file_type">File Types</label>
<select name="file_type" id="file_type">
<option value="pdf">PDFs only</option>
<option value="all">All files</option>
</select>
<input type="submit" name="submit" value="Submit" />
</form>
</metal:content-core>
</body>
</html>
<?xml version="1.0"?>
<object
i18n:domain="plone"
meta_type="Dexterity FTI"
name="Folder"
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<action
action_id="download_files"
category="object"
condition_expr=""
i18n:attributes="title"
title="Download Files"
url_expr="string:${object_url}/download_files"
visible="True">
<permission value="Modify portal content"/>
</action>
</object>
import os
import transaction
from datetime import datetime
from plone import api
from plone.namedfile import NamedBlobFile
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.statusmessages.interfaces import IStatusMessage
class DownloadFiles(BrowserView):
template = ViewPageTemplateFile('templates/download_files.pt')
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
form = self.request.form
if not form or 'file_type' not in form:
return self.template()
from_path = '/'.join(self.context.getPhysicalPath())
files = api.content.find(
path=from_path,
portal_type='File',
)
if not files:
IStatusMessage(self.request).addStatusMessage(u"No files found!", "info")
return self.template()
today = datetime.today().strftime("%Y-%m-%d")
exp_path = 'export-{0}-{1}'.format(self.context.id, today)
if os.path.exists(exp_path):
os.system('rm -rf {}'.format(exp_path))
os.mkdir(exp_path)
for file in files:
obj = file.getObject()
if form.get('file_type') == 'pdf' and 'pdf' not in obj.file.contentType:
continue
filename = obj.file.filename
f = open(os.path.join(exp_path, filename), 'wb')
f.write(obj.file.data)
f.close()
print("Saved {}".format(filename))
os.system('zip -r {0}.zip {0}'.format(exp_path))
os.system('rm -rf {}'.format(exp_path))
zip_file = api.content.create(
type='File',
title=exp_path,
container=self.context,
)
zip_file.file = NamedBlobFile(
data=open('{}.zip'.format(exp_path), 'r'),
filename=u'{}.zip'.format(exp_path),
contentType='application/zip'
)
zip_file.reindexObject()
transaction.commit()
self.request.response.redirect(zip_file.absolute_url() + '/view')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment