def serve(request, report_id): Report = get_report_model() report = get_object_or_404(Report, id=report_id) for fn in hooks.get_hooks('before_serve_report'): result = fn(report, request) if isinstance(result, HttpResponse): return result # Send report_served signal report_served.send(sender=Report, instance=report, request=request) try: local_path = report.file.path except NotImplementedError: local_path = None if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=True, attachment_filename=report.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile(request, local_path, attachment=True, attachment_filename=report.filename, backend=sendfile_streaming_backend.sendfile) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage). # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(report.file) response = StreamingHttpResponse( wrapper, content_type='application/octet-stream') try: response[ 'Content-Disposition'] = 'attachment; filename=%s' % report.filename except BadHeaderError: # Unicode filenames can fail on Django <1.8, Python 2 due to # https://code.djangoproject.com/ticket/20889 - try with an ASCIIfied version of the name response[ 'Content-Disposition'] = 'attachment; filename=%s' % unidecode( report.filename) # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = report.file.size return response
def serve(request, document_id, document_filename): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # We want to ensure that the document filename provided in the URL matches the one associated with the considered # document_id. If not we can't be sure that the document the user wants to access is the one corresponding to the # <document_id, document_filename> pair. if doc.filename != document_filename: raise Http404('This document does not match the given filename.') for fn in hooks.get_hooks('before_serve_document'): result = fn(doc, request) if isinstance(result, HttpResponse): return result # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) try: local_path = doc.file.path except NotImplementedError: local_path = None if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage). # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse( wrapper, content_type='application/octet-stream') response[ 'Content-Disposition'] = 'attachment; filename=%s' % doc.filename # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = doc.file.size return response
def serve(request, document_id, document_filename): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # We want to ensure that the document filename provided in the URL matches the one associated with the considered # document_id. If not we can't be sure that the document the user wants to access is the one corresponding to the # <document_id, document_filename> pair. if doc.filename != document_filename: raise Http404('This document does not match the given filename.') for fn in hooks.get_hooks('before_serve_document'): result = fn(doc, request) if isinstance(result, HttpResponse): return result # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) try: local_path = doc.file.path except NotImplementedError: local_path = None if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile( request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile ) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage). # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse(wrapper, content_type='application/octet-stream') response['Content-Disposition'] = 'attachment; filename=%s' % doc.filename # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = doc.file.size return response
def serve(request, document_id, document_filename): doc = get_object_or_404(Document, id=document_id) # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile)
def serve(request, document_id, document_filename): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) try: local_path = doc.file.path except NotImplementedError: local_path = None if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile( request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile ) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage). # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse(wrapper, content_type='application/octet-stream') try: response['Content-Disposition'] = 'attachment; filename=%s' % doc.filename except BadHeaderError: # Unicode filenames can fail on Django <1.8, Python 2 due to # https://code.djangoproject.com/ticket/20889 - try with an ASCIIfied version of the name response['Content-Disposition'] = 'attachment; filename=%s' % unidecode(doc.filename) # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = doc.file.size return response
def serve(request, document_id, document_filename): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # We want to ensure that the document filename provided in the URL matches the one associated with the considered # document_id. If not we can't be sure that the document the user wants to access is the one corresponding to the # <document_id, document_filename> pair. if doc.filename != document_filename: raise Http404('This document does not match the given filename.') for fn in hooks.get_hooks('before_serve_document'): result = fn(doc, request) if isinstance(result, HttpResponse): return result # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) try: local_path = doc.file.path except NotImplementedError: local_path = None try: direct_url = doc.file.url except NotImplementedError: direct_url = None serve_method = getattr(settings, 'WAGTAILDOCS_SERVE_METHOD', None) # If no serve method has been specified, select an appropriate default for the storage backend: # redirect for remote storages (i.e. ones that provide a url but not a local path) and # serve_view for all other cases if serve_method is None: if direct_url and not local_path: serve_method = 'redirect' else: serve_method = 'serve_view' if serve_method in ('redirect', 'direct') and direct_url: # Serve the file by redirecting to the URL provided by the underlying storage; # this saves the cost of delivering the file via Python. # For serve_method == 'direct', this view should not normally be reached # (the document URL as used in links should point directly to the storage URL instead) # but we handle it as a redirect to provide sensible fallback / # backwards compatibility behaviour. return redirect(direct_url) if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage) AND the developer has not allowed # redirecting to the file url directly. # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse( wrapper, content_type='application/octet-stream') response[ 'Content-Disposition'] = 'attachment; filename=%s' % doc.filename # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = doc.file.size return response
def serve(self, rendition): return sendfile(self.request, rendition.file.path, backend=self.backend)
def serve(request, document_id, document_filename): Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # We want to ensure that the document filename provided in the URL matches the one associated with the considered # document_id. If not we can't be sure that the document the user wants to access is the one corresponding to the # <document_id, document_filename> pair. if doc.filename != document_filename: raise Http404("This document does not match the given filename.") for fn in hooks.get_hooks("before_serve_document"): result = fn(doc, request) if isinstance(result, HttpResponse): return result # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) try: local_path = doc.file.path except NotImplementedError: local_path = None try: direct_url = doc.file.url except NotImplementedError: direct_url = None serve_method = getattr(settings, "WAGTAILDOCS_SERVE_METHOD", None) # If no serve method has been specified, select an appropriate default for the storage backend: # redirect for remote storages (i.e. ones that provide a url but not a local path) and # serve_view for all other cases if serve_method is None: if direct_url and not local_path: serve_method = "redirect" else: serve_method = "serve_view" if serve_method in ("redirect", "direct") and direct_url: # Serve the file by redirecting to the URL provided by the underlying storage; # this saves the cost of delivering the file via Python. # For serve_method == 'direct', this view should not normally be reached # (the document URL as used in links should point directly to the storage URL instead) # but we handle it as a redirect to provide sensible fallback / # backwards compatibility behaviour. return redirect(direct_url) if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends sendfile_opts = { "attachment": (doc.content_disposition != "inline"), "attachment_filename": doc.filename, "mimetype": doc.content_type, } if not hasattr(settings, "SENDFILE_BACKEND"): # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND sendfile_opts["backend"] = sendfile_streaming_backend.sendfile return sendfile(request, local_path, **sendfile_opts) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage) AND the developer has not allowed # redirecting to the file url directly. # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse(wrapper, doc.content_type) # set filename and filename* to handle non-ascii characters in filename # see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition response["Content-Disposition"] = doc.content_disposition # FIXME: storage backends are not guaranteed to implement 'size' response["Content-Length"] = doc.file.size return response
def serve_wagtail_doc(request, document_id, document_filename): """ Replacement for `wagtail.documents.views.serve` Substantial copying from original method: https://github.com/wagtail/wagtail/blob/master/wagtail/documents/views/serve.py Wagtail's default document view serves everything as an attachment. We'll bounce back to the URL and let the media server serve it. """ # these first two passages copied from wagtail/documents/views/serve.py Document = get_document_model() doc = get_object_or_404(Document, id=document_id) # We want to ensure that the document filename provided in the URL matches # the one associated with the considered document_id. If not we can't be # sure that the document the user wants to access is the one corresponding # to the <document_id, document_filename> pair. if doc.filename != document_filename: raise Http404('This document does not match the given filename.') for fn in hooks.get_hooks('before_serve_document'): result = fn(doc, request) if isinstance(result, HttpResponse): return result # Send document_served signal & log document_served.send(sender=Document, instance=doc, request=request) # ensure log output is valid CSV output = io.StringIO() writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC) writer.writerow( [document_id, document_filename, request.headers['User-Agent']]) logger.info(output.getvalue().strip()) try: local_path = doc.file.path except NotImplementedError: local_path = None try: direct_url = doc.file.url except NotImplementedError: direct_url = None serve_method = getattr(settings, 'WAGTAILDOCS_SERVE_METHOD', None) # If no serve method has been specified, select an appropriate default for the storage backend: # redirect for remote storages (i.e. ones that provide a url but not a local path) and # serve_view for all other cases if serve_method is None: if direct_url and not local_path: serve_method = 'redirect' else: serve_method = 'serve_view' if serve_method in ('redirect', 'direct') and direct_url: # Serve the file by redirecting to the URL provided by the underlying storage; # this saves the cost of delivering the file via Python. # For serve_method == 'direct', this view should not normally be reached # (the document URL as used in links should point directly to the storage URL instead) # but we handle it as a redirect to provide sensible fallback / # backwards compatibility behaviour. return redirect(direct_url) if local_path: # Use wagtail.utils.sendfile to serve the file; # this provides support for mimetypes, if-modified-since and django-sendfile backends if hasattr(settings, 'SENDFILE_BACKEND'): return sendfile(request, local_path, attachment=False, attachment_filename=doc.filename) else: # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND return sendfile(request, local_path, attachment=False, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile) else: # We are using a storage backend which does not expose filesystem paths # (e.g. storages.backends.s3boto.S3BotoStorage) AND the developer has not allowed # redirecting to the file url directly. # Fall back on pre-sendfile behaviour of reading the file content and serving it # as a StreamingHttpResponse wrapper = FileWrapper(doc.file) response = StreamingHttpResponse( wrapper, content_type='application/octet-stream') # FIXME: storage backends are not guaranteed to implement 'size' response['Content-Length'] = doc.file.size return response