Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
 def serve(self, rendition):
     return sendfile(self.request,
                     rendition.file.path,
                     backend=self.backend)
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
 def serve(self, rendition):
     return sendfile(self.request, rendition.file.path, backend=self.backend)