We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Documents: This backend doesn't support absolute paths. (Update to 1.0b2)
## 1. Bug since Wagtail update

I recently upgraded to 1.0b2 (from 1.0b1) and now, when I try to access I document I uploaded via a `wagtaildocs.Document` field, I get the following error:

```
NotImplementedError at /documents/3/headphones.svg
This backend doesn't support absolute paths.
```

The field is specified as:

```
svg_mask = models.ForeignKey(
    verbose_name=u"Mask (SVG)",
    to='wagtaildocs.Document',
    null=True,
    blank=True,
    on_delete=models.SET_NULL,
    related_name='+'
)
```

Is this a wagtail bug or a configuration error?
## 2. Unexpected behaviour

I would like to serve the svg as a `image/svg+xml`, not as a stream (which was the case in 1.0b1). I set the mimetype in my settings as follows:

```
mimetypes.add_type("image/svg+xml", ".svg", True)
mimetypes.add_type("image/svg+xml", ".svgz", True)
```

Yet (in 1.0b1) it always got served as a stream. I couldn't test it in 1.0b2 yet, because of the above problem.

Thank you in advance.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `wagtail/wagtaildocs/views/serve.py`
Content:
```
1 from django.shortcuts import get_object_or_404
2 from django.conf import settings
3 
4 from wagtail.utils.sendfile import sendfile
5 from wagtail.utils import sendfile_streaming_backend
6 
7 from wagtail.wagtaildocs.models import Document, document_served
8 
9 
10 def serve(request, document_id, document_filename):
11     doc = get_object_or_404(Document, id=document_id)
12 
13     # Send document_served signal
14     document_served.send(sender=Document, instance=doc, request=request)
15 
16     if hasattr(settings, 'SENDFILE_BACKEND'):
17         return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename)
18     else:
19         # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND
20         return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile)
21
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/wagtail/wagtaildocs/views/serve.py b/wagtail/wagtaildocs/views/serve.py
--- a/wagtail/wagtaildocs/views/serve.py
+++ b/wagtail/wagtaildocs/views/serve.py
@@ -1,5 +1,9 @@
 from django.shortcuts import get_object_or_404
 from django.conf import settings
+from django.http import StreamingHttpResponse, BadHeaderError
+
+from unidecode import unidecode
+from wsgiref.util import FileWrapper
 
 from wagtail.utils.sendfile import sendfile
 from wagtail.utils import sendfile_streaming_backend
@@ -13,8 +17,40 @@
     # 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)
+    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:
-        # 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)
+
+        # 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

{"golden_diff": "diff --git a/wagtail/wagtaildocs/views/serve.py b/wagtail/wagtaildocs/views/serve.py\n--- a/wagtail/wagtaildocs/views/serve.py\n+++ b/wagtail/wagtaildocs/views/serve.py\n@@ -1,5 +1,9 @@\n from django.shortcuts import get_object_or_404\n from django.conf import settings\n+from django.http import StreamingHttpResponse, BadHeaderError\n+\n+from unidecode import unidecode\n+from wsgiref.util import FileWrapper\n \n from wagtail.utils.sendfile import sendfile\n from wagtail.utils import sendfile_streaming_backend\n@@ -13,8 +17,40 @@\n     # Send document_served signal\n     document_served.send(sender=Document, instance=doc, request=request)\n \n-    if hasattr(settings, 'SENDFILE_BACKEND'):\n-        return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename)\n+    try:\n+        local_path = doc.file.path\n+    except NotImplementedError:\n+        local_path = None\n+\n+    if local_path:\n+\n+        # Use wagtail.utils.sendfile to serve the file;\n+        # this provides support for mimetypes, if-modified-since and django-sendfile backends\n+\n+        if hasattr(settings, 'SENDFILE_BACKEND'):\n+            return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename)\n+        else:\n+            # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND\n+            return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile)\n+\n     else:\n-        # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND\n-        return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile)\n+\n+        # We are using a storage backend which does not expose filesystem paths\n+        # (e.g. storages.backends.s3boto.S3BotoStorage).\n+        # Fall back on pre-sendfile behaviour of reading the file content and serving it\n+        # as a StreamingHttpResponse\n+\n+        wrapper = FileWrapper(doc.file)\n+        response = StreamingHttpResponse(wrapper, content_type='application/octet-stream')\n+\n+        try:\n+            response['Content-Disposition'] = 'attachment; filename=%s' % doc.filename\n+        except BadHeaderError:\n+            # Unicode filenames can fail on Django <1.8, Python 2 due to\n+            # https://code.djangoproject.com/ticket/20889 - try with an ASCIIfied version of the name\n+            response['Content-Disposition'] = 'attachment; filename=%s' % unidecode(doc.filename)\n+\n+        # FIXME: storage backends are not guaranteed to implement 'size'\n+        response['Content-Length'] = doc.file.size\n+\n+        return response\n", "issue": "Documents: This backend doesn't support absolute paths. (Update to 1.0b2)\n## 1. Bug since Wagtail update\n\nI recently upgraded to 1.0b2 (from 1.0b1) and now, when I try to access I document I uploaded via a `wagtaildocs.Document` field, I get the following error:\n\n```\nNotImplementedError at /documents/3/headphones.svg\nThis backend doesn't support absolute paths.\n```\n\nThe field is specified as:\n\n```\nsvg_mask = models.ForeignKey(\n    verbose_name=u\"Mask (SVG)\",\n    to='wagtaildocs.Document',\n    null=True,\n    blank=True,\n    on_delete=models.SET_NULL,\n    related_name='+'\n)\n```\n\nIs this a wagtail bug or a configuration error?\n## 2. Unexpected behaviour\n\nI would like to serve the svg as a `image/svg+xml`, not as a stream (which was the case in 1.0b1). I set the mimetype in my settings as follows:\n\n```\nmimetypes.add_type(\"image/svg+xml\", \".svg\", True)\nmimetypes.add_type(\"image/svg+xml\", \".svgz\", True)\n```\n\nYet (in 1.0b1) it always got served as a stream. I couldn't test it in 1.0b2 yet, because of the above problem.\n\nThank you in advance.\n\n", "before_files": [{"content": "from django.shortcuts import get_object_or_404\nfrom django.conf import settings\n\nfrom wagtail.utils.sendfile import sendfile\nfrom wagtail.utils import sendfile_streaming_backend\n\nfrom wagtail.wagtaildocs.models import Document, document_served\n\n\ndef serve(request, document_id, document_filename):\n    doc = get_object_or_404(Document, id=document_id)\n\n    # Send document_served signal\n    document_served.send(sender=Document, instance=doc, request=request)\n\n    if hasattr(settings, 'SENDFILE_BACKEND'):\n        return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename)\n    else:\n        # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND\n        return sendfile(request, doc.file.path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile)\n", "path": "wagtail/wagtaildocs/views/serve.py"}], "after_files": [{"content": "from django.shortcuts import get_object_or_404\nfrom django.conf import settings\nfrom django.http import StreamingHttpResponse, BadHeaderError\n\nfrom unidecode import unidecode\nfrom wsgiref.util import FileWrapper\n\nfrom wagtail.utils.sendfile import sendfile\nfrom wagtail.utils import sendfile_streaming_backend\n\nfrom wagtail.wagtaildocs.models import Document, document_served\n\n\ndef serve(request, document_id, document_filename):\n    doc = get_object_or_404(Document, id=document_id)\n\n    # Send document_served signal\n    document_served.send(sender=Document, instance=doc, request=request)\n\n    try:\n        local_path = doc.file.path\n    except NotImplementedError:\n        local_path = None\n\n    if local_path:\n\n        # Use wagtail.utils.sendfile to serve the file;\n        # this provides support for mimetypes, if-modified-since and django-sendfile backends\n\n        if hasattr(settings, 'SENDFILE_BACKEND'):\n            return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename)\n        else:\n            # Fallback to streaming backend if user hasn't specified SENDFILE_BACKEND\n            return sendfile(request, local_path, attachment=True, attachment_filename=doc.filename, backend=sendfile_streaming_backend.sendfile)\n\n    else:\n\n        # We are using a storage backend which does not expose filesystem paths\n        # (e.g. storages.backends.s3boto.S3BotoStorage).\n        # Fall back on pre-sendfile behaviour of reading the file content and serving it\n        # as a StreamingHttpResponse\n\n        wrapper = FileWrapper(doc.file)\n        response = StreamingHttpResponse(wrapper, content_type='application/octet-stream')\n\n        try:\n            response['Content-Disposition'] = 'attachment; filename=%s' % doc.filename\n        except BadHeaderError:\n            # Unicode filenames can fail on Django <1.8, Python 2 due to\n            # https://code.djangoproject.com/ticket/20889 - try with an ASCIIfied version of the name\n            response['Content-Disposition'] = 'attachment; filename=%s' % unidecode(doc.filename)\n\n        # FIXME: storage backends are not guaranteed to implement 'size'\n        response['Content-Length'] = doc.file.size\n\n        return response\n", "path": "wagtail/wagtaildocs/views/serve.py"}]}