Add zip file download for export with images

This commit is contained in:
JonnyWong16 2020-09-26 20:36:51 -07:00
parent b1eab8bb0d
commit 068cb51635
No known key found for this signature in database
GPG key ID: B1F1F9807184697A
2 changed files with 51 additions and 23 deletions

View file

@ -69,7 +69,6 @@ class Export(object):
self.items = [] self.items = []
self.filename = None self.filename = None
self.filename_ext = None
self.export_id = None self.export_id = None
self.file_size = None self.file_size = None
self.success = False self.success = False
@ -1205,8 +1204,9 @@ class Export(object):
if self.rating_key: if self.rating_key:
logger.debug( logger.debug(
"Tautulli Exporter :: Export called with rating_key %s, metadata_level %d, media_info_level %d", "Tautulli Exporter :: Export called with rating_key %s, "
self.rating_key, self.metadata_level, self.media_info_level) "metadata_level %d, media_info_level %d, include_images %s",
self.rating_key, self.metadata_level, self.media_info_level, self.include_images)
item = plex.get_item(self.rating_key) item = plex.get_item(self.rating_key)
self.media_type = item.type self.media_type = item.type
@ -1290,8 +1290,7 @@ class Export(object):
export_attrs = reduce(helpers.dict_merge, export_attrs_list) export_attrs = reduce(helpers.dict_merge, export_attrs_list)
self.filename = helpers.clean_filename(filename) self.filename = '{}.{}'.format(helpers.clean_filename(filename), self.file_format)
self.filename_ext = '{}.{}'.format(self.filename, self.file_format)
self.export_id = self.add_export() self.export_id = self.add_export()
@ -1305,9 +1304,9 @@ class Export(object):
return True return True
def _real_export(self, attrs): def _real_export(self, attrs):
logger.info("Tautulli Exporter :: Starting export for '%s'...", self.filename_ext) logger.info("Tautulli Exporter :: Starting export for '%s'...", self.filename)
filepath = get_export_filepath(self.filename_ext) filepath = get_export_filepath(self.filename)
part = partial(helpers.get_attrs_to_dict, attrs=attrs) part = partial(helpers.get_attrs_to_dict, attrs=attrs)
pool = ThreadPool(processes=4) pool = ThreadPool(processes=4)
@ -1331,7 +1330,7 @@ class Export(object):
self.file_size = os.path.getsize(filepath) self.file_size = os.path.getsize(filepath)
if self.include_images: if self.include_images:
images_folder = get_export_filepath('{}.images'.format(self.filename)) images_folder = get_export_filepath(self.filename, images=True)
for f in os.listdir(images_folder): for f in os.listdir(images_folder):
image_path = os.path.join(images_folder, f) image_path = os.path.join(images_folder, f)
if os.path.isfile(image_path): if os.path.isfile(image_path):
@ -1341,7 +1340,7 @@ class Export(object):
logger.info("Tautulli Exporter :: Successfully exported to '%s'", filepath) logger.info("Tautulli Exporter :: Successfully exported to '%s'", filepath)
except Exception as e: except Exception as e:
logger.error("Tautulli Exporter :: Failed to export '%s': %s", self.filename_ext, e) logger.error("Tautulli Exporter :: Failed to export '%s': %s", self.filename, e)
import traceback import traceback
traceback.print_exc() traceback.print_exc()
@ -1357,7 +1356,7 @@ class Export(object):
'media_type': self.media_type} 'media_type': self.media_type}
values = {'file_format': self.file_format, values = {'file_format': self.file_format,
'filename': self.filename_ext, 'filename': self.filename,
'include_images': self.include_images} 'include_images': self.include_images}
db = database.MonitorDatabase() db = database.MonitorDatabase()
@ -1397,8 +1396,10 @@ def get_image(item, image, export_filename):
else: else:
item_title = item.title item_title = item.title
folder = get_export_filepath('{}.images'.format(export_filename)) folder = get_export_filepath(export_filename, images=True)
filepath = os.path.join(folder, '{} [{}].{}.jpg'.format(item_title, rating_key, image)) filename = helpers.clean_filename('{} [{}].{}.jpg'.format(item_title, rating_key, image))
filepath = os.path.join(folder, filename)
if not os.path.exists(folder): if not os.path.exists(folder):
os.makedirs(folder) os.makedirs(folder)
@ -1422,7 +1423,7 @@ def get_image(item, image, export_filename):
def get_export(export_id): def get_export(export_id):
db = database.MonitorDatabase() db = database.MonitorDatabase()
result = db.select_single('SELECT filename, file_format, complete ' result = db.select_single('SELECT filename, file_format, include_images, complete '
'FROM exports WHERE id = ?', 'FROM exports WHERE id = ?',
[export_id]) [export_id])
@ -1445,9 +1446,10 @@ def delete_export(export_id):
logger.info("Tautulli Exporter :: Deleting exported file from '%s'.", filepath) logger.info("Tautulli Exporter :: Deleting exported file from '%s'.", filepath)
try: try:
os.remove(filepath) os.remove(filepath)
folder = '{}.images'.format(os.path.splitext(filepath)[0]) if export_data['include_images']:
if os.path.exists(folder): images_folder = get_export_filepath(export_data['filename'], images=True)
shutil.rmtree(folder) if os.path.exists(images_folder):
shutil.rmtree(images_folder)
except OSError as e: except OSError as e:
logger.error("Tautulli Exporter :: Failed to delete exported file '%s': %s", filepath, e) logger.error("Tautulli Exporter :: Failed to delete exported file '%s': %s", filepath, e)
return True return True
@ -1457,7 +1459,7 @@ def delete_export(export_id):
def delete_all_exports(): def delete_all_exports():
db = database.MonitorDatabase() db = database.MonitorDatabase()
result = db.select('SELECT filename FROM exports') result = db.select('SELECT filename, include_images FROM exports')
logger.info("Tautulli Exporter :: Deleting all exports from the database.") logger.info("Tautulli Exporter :: Deleting all exports from the database.")
@ -1467,9 +1469,10 @@ def delete_all_exports():
filepath = get_export_filepath(row['filename']) filepath = get_export_filepath(row['filename'])
try: try:
os.remove(filepath) os.remove(filepath)
folder = '{}.images'.format(os.path.splitext(filepath)[0]) if row['include_images']:
if os.path.exists(folder): images_folder = get_export_filepath(row['filename'], images=True)
shutil.rmtree(folder) if os.path.exists(images_folder):
shutil.rmtree(images_folder)
except OSError as e: except OSError as e:
logger.error("Tautulli Exporter :: Failed to delete exported file '%s': %s", filepath, e) logger.error("Tautulli Exporter :: Failed to delete exported file '%s': %s", filepath, e)
deleted_files = False deleted_files = False
@ -1556,7 +1559,10 @@ def get_export_datatable(section_id=None, rating_key=None, kwargs=None):
return result return result
def get_export_filepath(filename): def get_export_filepath(filename, images=False):
if images:
images_folder = '{}.images'.format(os.path.splitext(filename)[0])
return os.path.join(plexpy.CONFIG.EXPORT_DIR, images_folder)
return os.path.join(plexpy.CONFIG.EXPORT_DIR, filename) return os.path.join(plexpy.CONFIG.EXPORT_DIR, filename)

View file

@ -21,7 +21,7 @@ from future.builtins import object
from future.builtins import str from future.builtins import str
from backports import csv from backports import csv
from io import open from io import open, BytesIO
import base64 import base64
import json import json
import linecache import linecache
@ -29,10 +29,11 @@ import os
import shutil import shutil
import sys import sys
import threading import threading
import zipfile
from future.moves.urllib.parse import urlencode from future.moves.urllib.parse import urlencode
import cherrypy import cherrypy
from cherrypy.lib.static import serve_file, serve_download from cherrypy.lib.static import serve_file, serve_fileobj, serve_download
from cherrypy._cperror import NotFound from cherrypy._cperror import NotFound
from hashing_passwords import make_hash from hashing_passwords import make_hash
@ -6594,6 +6595,27 @@ class WebInterface(object):
result = exporter.get_export(export_id=export_id) result = exporter.get_export(export_id=export_id)
if result and result['complete'] == 1 and result['exists']: if result and result['complete'] == 1 and result['exists']:
export_filepath = exporter.get_export_filepath(result['filename'])
if result['include_images']:
zip_filename = '{}.zip'.format(os.path.splitext(result['filename'])[0])
images_folder = exporter.get_export_filepath(result['filename'], images=True)
if os.path.exists(images_folder):
buffer = BytesIO()
temp_zip = zipfile.ZipFile(buffer, 'w')
temp_zip.write(export_filepath, arcname=result['filename'])
_images_folder = os.path.basename(images_folder)
for f in os.listdir(images_folder):
image_path = os.path.join(images_folder, f)
temp_zip.write(image_path, arcname=os.path.join(_images_folder, f))
temp_zip.close()
return serve_fileobj(buffer.getvalue(), content_type='application/zip',
disposition='attachment', name=zip_filename)
return serve_download(exporter.get_export_filepath(result['filename']), name=result['filename']) return serve_download(exporter.get_export_filepath(result['filename']), name=result['filename'])
else: else:
if result and result.get('complete') == 0: if result and result.get('complete') == 0: