Files
mayan-edms/mayan/apps/sources/classes.py
Roberto Rosario c7e9a4dc99 Add keyword arguments
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
2019-05-12 02:09:26 -04:00

175 lines
5.8 KiB
Python

from __future__ import unicode_literals
import base64
import logging
import os
import time
from furl import furl
from django.core.files import File
from django.core.files.base import ContentFile
from django.urls import reverse
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.six.moves.urllib.parse import quote_plus, unquote_plus
from mayan.apps.converter.transformations import TransformationResize
from mayan.apps.converter.utils import get_converter_class
from .storages import storage_staging_file_image_cache
logger = logging.getLogger(__name__)
class PseudoFile(File):
def __init__(self, file, name):
self.name = name
self.file = file
self.file.seek(0, os.SEEK_END)
self.size = self.file.tell()
self.file.seek(0)
class SourceUploadedFile(File):
def __init__(self, source, file, extra_data=None):
self.file = file
self.source = source
self.extra_data = extra_data
@python_2_unicode_compatible
class StagingFile(object):
"""
Simple class to extend the File class to add preview capabilities
files in a directory on a storage
"""
def __init__(self, staging_folder, filename=None, encoded_filename=None):
self.staging_folder = staging_folder
if encoded_filename:
self.encoded_filename = str(encoded_filename)
self.filename = base64.urlsafe_b64decode(
unquote_plus(self.encoded_filename)
).decode('utf8')
else:
self.filename = filename
self.encoded_filename = quote_plus(base64.urlsafe_b64encode(
filename.encode('utf8')
))
def __str__(self):
return force_text(self.filename)
def as_file(self):
return File(
file=open(self.get_full_path(), mode='rb'), name=self.filename
)
@property
def cache_filename(self):
return '{}{}'.format(self.staging_folder.pk, self.encoded_filename)
def delete(self):
storage_staging_file_image_cache.delete(self.cache_filename)
os.unlink(self.get_full_path())
def generate_image(self, *args, **kwargs):
transformation_list = self.get_combined_transformation_list(*args, **kwargs)
# Check is transformed image is available
logger.debug('transformations cache filename: %s', self.cache_filename)
if storage_staging_file_image_cache.exists(self.cache_filename):
logger.debug(
'staging file cache file "%s" found', self.cache_filename
)
else:
logger.debug(
'staging file cache file "%s" not found', self.cache_filename
)
image = self.get_image(transformations=transformation_list)
with storage_staging_file_image_cache.open(self.cache_filename, 'wb+') as file_object:
file_object.write(image.getvalue())
return self.cache_filename
def get_api_image_url(self, *args, **kwargs):
final_url = furl()
final_url.args = kwargs
final_url.path = reverse(
'rest_api:stagingfolderfile-image-view', kwargs={
'staging_folder_pk': self.staging_folder.pk,
'encoded_filename': self.encoded_filename
}
)
return final_url.tostr()
def get_combined_transformation_list(self, *args, **kwargs):
"""
Return a list of transformation containing the server side
staging file transformation as well as tranformations created
from the arguments as transient interactive transformation.
"""
# Convert arguments into transformations
transformations = kwargs.get('transformations', [])
# Set sensible defaults if the argument is not specified or if the
# argument is None
width = self.staging_folder.preview_width
height = self.staging_folder.preview_height
# Generate transformation hash
transformation_list = []
# Interactive transformations second
for transformation in transformations:
transformation_list.append(transformation)
if width:
transformation_list.append(
TransformationResize(width=width, height=height)
)
return transformation_list
def get_date_time_created(self):
return time.ctime(os.path.getctime(self.get_full_path()))
def get_full_path(self):
return os.path.join(self.staging_folder.folder_path, self.filename)
def get_image(self, transformations=None):
cache_filename = self.cache_filename
file_object = None
try:
file_object = open(self.get_full_path(), mode='rb')
converter = get_converter_class()(file_object=file_object)
page_image = converter.get_page()
# Since open "wb+" doesn't create files, check if the file
# exists, if not then create it
if not storage_staging_file_image_cache.exists(cache_filename):
storage_staging_file_image_cache.save(name=cache_filename, content=ContentFile(content=''))
with storage_staging_file_image_cache.open(cache_filename, 'wb+') as file_object:
file_object.write(page_image.getvalue())
except Exception as exception:
# Cleanup in case of error
logger.error(
'Error creating staging file cache "%s"; %s',
cache_filename, exception
)
storage_staging_file_image_cache.delete(cache_filename)
if file_object:
file_object.close()
raise
for transformation in transformations:
converter.transform(transformation=transformation)
result = converter.get_page()
file_object.close()
return result