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 test_count(self): fake_file = ContentFile(b("Example document")) fake_file.name = 'test.txt' document = Document.objects.create(title="Test document", file=fake_file) counter = DownloadCount.objects.create(file=document) assert counter.count is 0 document_served.send(sender=Document, instance=document) counter.refresh_from_db() assert counter.count is 1
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): 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 document_serve(request, document_id, document_filename): doc = get_object_or_404(Document, id=document_id) wrapper = FileWrapper(doc.file) response = StreamingHttpResponse(wrapper, content_type='application/pdf') response['Content-Length'] = doc.file.size # Send document_served signal document_served.send(sender=doc, request=request) return response
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): doc = get_object_or_404(Document, id=document_id) wrapper = FileWrapper(doc.file) response = HttpResponse(wrapper, content_type="application/octet-stream") # TODO: strip out weird characters like semicolons from the filename # (there doesn't seem to be an official way of escaping them) response["Content-Disposition"] = "attachment; filename=%s" % doc.filename response["Content-Length"] = doc.file.size # Send document_served signal document_served.send(sender=doc, request=request) return response
def serve(request, document_id, document_filename): doc = get_object_or_404(Document, id=document_id) wrapper = FileWrapper(doc.file) response = HttpResponse(wrapper, content_type='application/octet-stream') # TODO: strip out weird characters like semicolons from the filename # (there doesn't seem to be an official way of escaping them) response['Content-Disposition'] = 'attachment; filename=%s' % doc.filename response['Content-Length'] = doc.file.size # Send document_served signal document_served.send(sender=doc, request=request) return response
def serve(request, document_id, document_filename): doc = get_object_or_404(Document, id=document_id) 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) response['Content-Length'] = doc.file.size # Send document_served signal document_served.send(sender=doc, request=request) return response
def serve(request, document_id, document_filename): doc = get_object_or_404(Document, id=document_id) wrapper = FileWrapper(doc.file) response = HttpResponse(wrapper, content_type=mimetypes.guess_type(doc.filename)[0]) # Make PDFs open in the browser where possible rather than save if doc.file_extension == 'pdf': response['Content-Disposition'] = 'filename=%s' % doc.filename else: # TODO: strip out weird characters like semicolons from the filename # (there doesn't seem to be an official way of escaping them) response['Content-Disposition'] = 'attachment; filename=%s' % doc.filename response['Content-Length'] = doc.file.size # Send document_served signal document_served.send(sender=doc, request=request) return response
def serve(request, document_id, document_filename): doc = get_object_or_404(Document, id=document_id) 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) response['Content-Length'] = doc.file.size # Send document_served signal document_served.send(sender=Document, instance=doc, request=request) return response