--- a/src/pyams_file/views/file.py Thu Oct 08 09:22:40 2015 +0200
+++ b/src/pyams_file/views/file.py Thu Apr 21 16:37:47 2016 +0200
@@ -14,10 +14,10 @@
# import standard library
-from http.client import NOT_MODIFIED
+from http.client import NOT_MODIFIED, PARTIAL_CONTENT
# import interfaces
-from pyams_file.interfaces import IFile, IMediaFile
+from pyams_file.interfaces import IFile
from zope.dublincore.interfaces import IZopeDublinCore
# import packages
@@ -25,6 +25,9 @@
from pyramid.view import view_config
+MAX_RANGE_LENGTH = 1 << 21 # 2 Mb
+
+
@view_config(context=IFile)
def FileView(request):
"""Default file view"""
@@ -38,27 +41,27 @@
status=NOT_MODIFIED)
response = Response(content_type=context.content_type.decode('utf-8'),
- content_disposition='attachment; filename="{0}"'.format(context.filename),
last_modified=modified)
- response.body_file = context.get_blob(mode='c')
- return response
-
+ body_file = context.get_blob(mode='c')
-@view_config(context=IMediaFile)
-def MediaFileView(request):
- """Default media file view"""
- context = request.context
-
- # check for last modification date
- modified = IZopeDublinCore(context).modified
- if_modified_since = request.if_modified_since
- if if_modified_since and (int(modified.timestamp()) <= int(if_modified_since.timestamp())):
- return Response(content_type=context.content_type.decode('utf-8'),
- status=NOT_MODIFIED)
-
- response = Response(content_type=context.content_type.decode('utf-8'),
- last_modified=modified)
if request.params.get('download') is not None:
response.content_disposition = 'attachment; filename="{0}"'.format(context.filename)
- response.body_file = context.get_blob(mode='c')
+
+ if request.range is not None:
+ body = body_file.read()
+ body_length = len(body)
+ range_start = request.range.start or 0
+ if 'Firefox' in request.user_agent: # avoid partial range for Firefox videos
+ range_end = body_length
+ else:
+ range_end = request.range.end or min(body_length, range_start + MAX_RANGE_LENGTH)
+ ranged_body = body[range_start:range_end]
+ response.status = PARTIAL_CONTENT
+ response.headers['Content-Range'] = 'bytes {first}-{last}/{len}'.format(first=range_start,
+ last=range_start + len(ranged_body) - 1,
+ len=body_length)
+ response.body = ranged_body
+ else:
+ response.body_file = body_file
+
return response