Added document preview link and download link

This commit is contained in:
Roberto Rosario
2011-02-08 19:07:00 -04:00
parent 79d7932df0
commit dabe8fad19
9 changed files with 147 additions and 6 deletions

View File

@@ -5,4 +5,22 @@
{% block content %} {% block content %}
{% include 'generic_list_subtemplate.html' %} {% include 'generic_list_subtemplate.html' %}
{% for subtemplate in subtemplates_dict %}
{% with subtemplate.title as title %}
{% with subtemplate.object_list as object_list %}
{% with subtemplate.extra_columns as extra_columns %}
{% with subtemplate.hide_object as hide_object %}
{% with subtemplate.main_object as main_object %}
{% with subtemplate.hide_link as hide_link %}
{% include subtemplate.name %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %}
{% endblock %} {% endblock %}

View File

@@ -11,10 +11,12 @@ document_create_multiple = {'text':_('upload multiple documents'), 'view':'docum
document_view = {'text':_('details'), 'view':'document_view', 'args':'object.id', 'famfam':'page'} document_view = {'text':_('details'), 'view':'document_view', 'args':'object.id', 'famfam':'page'}
document_delete = {'text':_('delete'), 'view':'document_delete', 'args':'object.id', 'famfam':'page_delete'} document_delete = {'text':_('delete'), 'view':'document_delete', 'args':'object.id', 'famfam':'page_delete'}
document_edit = {'text':_('edit'), 'view':'document_edit', 'args':'object.id', 'famfam':'page_edit'} document_edit = {'text':_('edit'), 'view':'document_edit', 'args':'object.id', 'famfam':'page_edit'}
document_preview = {'text':_('preview'), 'class':'fancybox', 'view':'document_preview', 'args':'object.id', 'famfam':'magnifier'}
document_download = {'text':_('download'), 'view':'document_download', 'args':'object.id', 'famfam':'page_save'}
staging_file_preview = {'class':'fancybox', 'text':_('preview'), 'view':'staging_file_preview', 'args':'object.id', 'famfam':'drive_magnify'} staging_file_preview = {'text':_('preview'), 'class':'fancybox', 'view':'staging_file_preview', 'args':'object.id', 'famfam':'drive_magnify'}
register_links(Document, [document_view, document_edit, document_delete]) register_links(Document, [document_view, document_edit, document_delete, document_preview, document_download])
register_links(Document, [document_list, document_create, document_create_multiple], menu_name='sidebar') register_links(Document, [document_list, document_create, document_create_multiple], menu_name='sidebar')
register_links(['document_list', 'document_create', 'document_create_multiple', 'upload_document_with_type', 'upload_multiple_documents_with_type'], [document_list, document_create, document_create_multiple], menu_name='sidebar') register_links(['document_list', 'document_create', 'document_create_multiple', 'upload_document_with_type', 'upload_multiple_documents_with_type'], [document_list, document_create, document_create_multiple], menu_name='sidebar')

View File

@@ -23,7 +23,6 @@ USE_STAGING_DIRECTORY = getattr(settings, 'DOCUMENTS_USE_STAGING_DIRECTORY', Fal
STAGING_DIRECTORY = getattr(settings, 'DOCUMENTS_STAGING_DIRECTORY', u'/tmp/mayan/staging') STAGING_DIRECTORY = getattr(settings, 'DOCUMENTS_STAGING_DIRECTORY', u'/tmp/mayan/staging')
DELETE_STAGING_FILE_AFTER_UPLOAD = getattr(settings, 'DOCUMENTS_DELETE_STAGING_FILE_AFTER_UPLOAD', False) DELETE_STAGING_FILE_AFTER_UPLOAD = getattr(settings, 'DOCUMENTS_DELETE_STAGING_FILE_AFTER_UPLOAD', False)
STAGING_FILES_PREVIEW_SIZE = getattr(settings, 'DOCUMENTS_STAGING_FILES_PREVIEW_SIZE', '640x480') STAGING_FILES_PREVIEW_SIZE = getattr(settings, 'DOCUMENTS_STAGING_FILES_PREVIEW_SIZE', '640x480')
DELETE_LOCAL_ORIGINAL = getattr(settings, 'DOCUMENTS_DELETE_LOCAL_ORIGINAL', False) DELETE_LOCAL_ORIGINAL = getattr(settings, 'DOCUMENTS_DELETE_LOCAL_ORIGINAL', False)
# Saving # Saving
CHECKSUM_FUNCTION = getattr(settings, 'DOCUMENTS_CHECKSUM_FUNCTION', lambda x: hashlib.sha256(x).hexdigest()) CHECKSUM_FUNCTION = getattr(settings, 'DOCUMENTS_CHECKSUM_FUNCTION', lambda x: hashlib.sha256(x).hexdigest())
@@ -31,6 +30,8 @@ UUID_FUNCTION = getattr(settings, 'DOCUMENTS_UUID_FUNTION', lambda:unicode(uuid.
# Storage # Storage
STORAGE_BACKEND = getattr(settings, 'DOCUMENTS_STORAGE_BACKEND', DocumentStorage) STORAGE_BACKEND = getattr(settings, 'DOCUMENTS_STORAGE_BACKEND', DocumentStorage)
STORAGE_DIRECTORY_NAME = getattr(settings, 'DOCUMENTS_STORAGE_DIRECTORY_NAME', 'documents') STORAGE_DIRECTORY_NAME = getattr(settings, 'DOCUMENTS_STORAGE_DIRECTORY_NAME', 'documents')
# Usage
PREVIEW_SIZE = getattr(settings, 'DOCUMENTS_PREVIEW_SIZE', '640x480')
# Serving # Serving
FILESYSTEM_FILESERVING_ENABLE = getattr(settings, 'DOCUMENTS_FILESYSTEM_FILESERVING_ENABLE', True) FILESYSTEM_FILESERVING_ENABLE = getattr(settings, 'DOCUMENTS_FILESYSTEM_FILESERVING_ENABLE', True)
FILESYSTEM_FILESERVING_PATH = getattr(settings, 'DOCUMENTS_FILESERVING_PATH', u'/tmp/mayan/documents') FILESYSTEM_FILESERVING_PATH = getattr(settings, 'DOCUMENTS_FILESERVING_PATH', u'/tmp/mayan/documents')

View File

@@ -6,6 +6,19 @@ import tempfile
#from django.core.files.base import File #from django.core.files.base import File
from documents.conf.settings import TEMPORARY_DIRECTORY from documents.conf.settings import TEMPORARY_DIRECTORY
def in_cache(input_filepath, size, page=0, format='jpg'):
temp_directory = TEMPORARY_DIRECTORY if TEMPORARY_DIRECTORY else tempfile.mkdtemp()
temp_filename, separator = os.path.splitext(os.path.basename(input_filepath))
temp_path = os.path.join(temp_directory, temp_filename)
output_arg = '%s_%s%s%s' % (temp_path, size, os.extsep, format)
input_arg = '%s[%s]' % (input_filepath, page)
if os.path.exists(output_arg):
return output_arg
else:
return None
def convert(input_filepath, size, cache=True, page=0, format='jpg'): def convert(input_filepath, size, cache=True, page=0, format='jpg'):
temp_directory = TEMPORARY_DIRECTORY if TEMPORARY_DIRECTORY else tempfile.mkdtemp() temp_directory = TEMPORARY_DIRECTORY if TEMPORARY_DIRECTORY else tempfile.mkdtemp()
#TODO: generate output file using lightweight hash function on #TODO: generate output file using lightweight hash function on

View File

@@ -73,6 +73,9 @@ class Document(models.Model):
def __unicode__(self): def __unicode__(self):
return '%s.%s' % (self.file_filename, self.file_extension) return '%s.%s' % (self.file_filename, self.file_extension)
def get_fullname(self):
return os.extsep.join([self.file_filename, self.file_extension])
@models.permalink @models.permalink
def get_absolute_url(self): def get_absolute_url(self):

View File

@@ -12,6 +12,8 @@ urlpatterns = patterns('documents.views',
url(r'^document/(?P<document_id>\d+)/$', 'document_view', (), 'document_view'), url(r'^document/(?P<document_id>\d+)/$', 'document_view', (), 'document_view'),
url(r'^document/(?P<document_id>\d+)/delete/$', 'document_delete', (), 'document_delete'), url(r'^document/(?P<document_id>\d+)/delete/$', 'document_delete', (), 'document_delete'),
url(r'^document/(?P<document_id>\d+)/edit/$', 'document_edit', (), 'document_edit'), url(r'^document/(?P<document_id>\d+)/edit/$', 'document_edit', (), 'document_edit'),
url(r'^document/(?P<document_id>\d+)/preview/$', 'document_preview', (), 'document_preview'),
url(r'^document/(?P<document_id>\d+)/download/$', 'document_download', (), 'document_download'),
url(r'^staging_file/(?P<staging_file_id>\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'), url(r'^staging_file/(?P<staging_file_id>\w+)/preview/$', 'staging_file_preview', (), 'staging_file_preview'),

61
apps/documents/utils.py Normal file
View File

@@ -0,0 +1,61 @@
import os
import tempfile
from documents.conf.settings import TEMPORARY_DIRECTORY
#http://stackoverflow.com/questions/123198/how-do-i-copy-a-file-in-python
def copyfile(source, dest, buffer_size=1024*1024):
"""
Copy a file from source to dest. source and dest
can either be strings or any object with a read or
write method, like StringIO for example.
"""
if not hasattr(source, 'read'):
source = open(source, 'rb')
if not hasattr(dest, 'write'):
dest = open(dest, 'wb')
while 1:
copy_buffer = source.read(buffer_size)
if copy_buffer:
dest.write(copy_buffer)
else:
break
source.close()
dest.close()
def from_descriptor_to_tempfile(input_descriptor, filename, buffer_size=1024*1024):
path = os.path.join(TEMPORARY_DIRECTORY, filename)
output_descriptor = open(path, 'wb')
while 1:
copy_buffer = input_descriptor.read(buffer_size)
if copy_buffer:
output_descriptor.write(copy_buffer)
else:
break
input_descriptor.close()
output_descriptor.close()
return path
def from_descriptor_to_new_tempfile(input_descriptor, buffer_size=1024*1024):
output_descriptor, tmp_filename = tempfile.mkstemp()
while 1:
copy_buffer = input_descriptor.read(buffer_size)
if copy_buffer:
#output_descriptor.write(copy_buffer)
os.write(output_descriptor, copy_buffer)
else:
break
input_descriptor.close()
os.close(output_descriptor)
return tmp_filename

View File

@@ -1,4 +1,3 @@
from urlparse import urlparse
from urllib import unquote_plus from urllib import unquote_plus
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@@ -14,7 +13,8 @@ from django.core.files.base import File
from filetransfers.api import serve_file from filetransfers.api import serve_file
from convert import convert from convert import convert, in_cache
from utils import from_descriptor_to_tempfile
from models import Document, DocumentMetadata, DocumentType, MetadataType from models import Document, DocumentMetadata, DocumentType, MetadataType
from forms import DocumentTypeSelectForm, DocumentCreateWizard, \ from forms import DocumentTypeSelectForm, DocumentCreateWizard, \
@@ -27,6 +27,7 @@ from documents.conf.settings import DELETE_STAGING_FILE_AFTER_UPLOAD
from documents.conf.settings import USE_STAGING_DIRECTORY from documents.conf.settings import USE_STAGING_DIRECTORY
from documents.conf.settings import FILESYSTEM_FILESERVING_ENABLE from documents.conf.settings import FILESYSTEM_FILESERVING_ENABLE
from documents.conf.settings import STAGING_FILES_PREVIEW_SIZE from documents.conf.settings import STAGING_FILES_PREVIEW_SIZE
from documents.conf.settings import PREVIEW_SIZE
def document_list(request): def document_list(request):
return object_list( return object_list(
@@ -39,10 +40,14 @@ def document_list(request):
{'name':_(u'mimetype'), 'attribute':'file_mimetype'}, {'name':_(u'mimetype'), 'attribute':'file_mimetype'},
{'name':_(u'added'), 'attribute':lambda x: x.date_added.date()}, {'name':_(u'added'), 'attribute':lambda x: x.date_added.date()},
], ],
'subtemplates_dict':[
{
'name':'fancybox.html',
},
],
}, },
) )
def document_create(request, multiple=True): def document_create(request, multiple=True):
MetadataFormSet = formset_factory(MetadataForm, extra=0) MetadataFormSet = formset_factory(MetadataForm, extra=0)
wizard = DocumentCreateWizard(form_list=[DocumentTypeSelectForm, MetadataFormSet], multiple=multiple) wizard = DocumentCreateWizard(form_list=[DocumentTypeSelectForm, MetadataFormSet], multiple=multiple)
@@ -198,6 +203,9 @@ def document_view(request, document_id):
]) ])
subtemplates_dict = [ subtemplates_dict = [
{
'name':'fancybox.html',
},
{ {
'name':'generic_list_subtemplate.html', 'name':'generic_list_subtemplate.html',
'title':_(u'metadata'), 'title':_(u'metadata'),
@@ -274,6 +282,37 @@ def document_edit(request, document_id):
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def document_preview(request, document_id):
document = get_object_or_404(Document, pk=document_id)
filepath = in_cache(document.uuid, PREVIEW_SIZE)
if filepath:
return serve_file(request, File(file=open(filepath, 'r')))
else:
try:
document.file.open()
desc = document.file.storage.open(document.file.path)
filepath = from_descriptor_to_tempfile(desc, document.uuid)
output_file = convert(filepath, PREVIEW_SIZE)
return serve_file(request, File(file=open(output_file, 'r')))
except Exception, e:
#messages.error(request, e)
return HttpResponse(e)
def document_download(request, document_id):
document = get_object_or_404(Document, pk=document_id)
try:
#Test permissions and trigger exception
document.file.open()
return serve_file(request, document.file, save_as=document.get_fullname())
except Exception, e:
messages.error(request, e)
return HttpResponseRedirect(request.META['HTTP_REFERER'])
def staging_file_preview(request, staging_file_id): def staging_file_preview(request, staging_file_id):
try: try:
filepath = StagingFile.get(staging_file_id).filepath filepath = StagingFile.get(staging_file_id).filepath

View File

@@ -180,6 +180,8 @@ LOGIN_EXEMPT_URLS = (
#DOCUMENTS_UUID_FUNCTION = lambda:unicode(uuid.uuid4()) #DOCUMENTS_UUID_FUNCTION = lambda:unicode(uuid.uuid4())
# Storage # Storage
#DOCUMENTS_STORAGE_DIRECTORY_NAME = 'documents' #DOCUMENTS_STORAGE_DIRECTORY_NAME = 'documents'
# Usage
#DOCUMENTS_PREVIEW_SIZE = '640x480'
# Serving # Serving
#DOCUMENTS_FILESYSTEM_FILESERVING_ENABLE = True #DOCUMENTS_FILESYSTEM_FILESERVING_ENABLE = True
#DOCUMENTS_FILESYSTEM_FILESERVING_PATH = u'/tmp/mayan/documents' #DOCUMENTS_FILESYSTEM_FILESERVING_PATH = u'/tmp/mayan/documents'