From de4832c49b8a8cf00b2d602ab4d10c4ca69627bd Mon Sep 17 00:00:00 2001
From: ShingenPizza <19253513+ShingenPizza@users.noreply.github.com>
Date: Fri, 17 May 2019 12:07:27 +0200
Subject: [PATCH] Fixed #30196 -- Made FileResponse set Content-Disposition
 inline if filename is available.

---
 django/http/response.py              | 20 +++++++++++---------
 docs/ref/request-response.txt        | 12 +++++++-----
 tests/responses/test_fileresponse.py |  9 +++++++++
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/django/http/response.py b/django/http/response.py
index a9ede09dd9..04efbd6bef 100644
--- a/django/http/response.py
+++ b/django/http/response.py
@@ -436,15 +436,17 @@ class FileResponse(StreamingHttpResponse):
             else:
                 self['Content-Type'] = 'application/octet-stream'
 
-        if self.as_attachment:
-            filename = self.filename or os.path.basename(filename)
-            if filename:
-                try:
-                    filename.encode('ascii')
-                    file_expr = 'filename="{}"'.format(filename)
-                except UnicodeEncodeError:
-                    file_expr = "filename*=utf-8''{}".format(quote(filename))
-                self['Content-Disposition'] = 'attachment; {}'.format(file_expr)
+        filename = self.filename or os.path.basename(filename)
+        if filename:
+            disposition = 'attachment' if self.as_attachment else 'inline'
+            try:
+                filename.encode('ascii')
+                file_expr = 'filename="{}"'.format(filename)
+            except UnicodeEncodeError:
+                file_expr = "filename*=utf-8''{}".format(quote(filename))
+            self['Content-Disposition'] = '{}; {}'.format(disposition, file_expr)
+        elif self.as_attachment:
+            self['Content-Disposition'] = 'attachment'
 
 
 class HttpResponseRedirectBase(HttpResponse):
diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
index 58a7c3e7e4..28e5170595 100644
--- a/docs/ref/request-response.txt
+++ b/docs/ref/request-response.txt
@@ -1107,15 +1107,17 @@ Attributes
     optimized for binary files. It uses `wsgi.file_wrapper`_ if provided by the
     wsgi server, otherwise it streams the file out in small chunks.
 
-    If ``as_attachment=True``, the ``Content-Disposition`` header is set, which
-    asks the browser to offer the file to the user as a download.
+    If ``as_attachment=True``, the ``Content-Disposition`` header is set to
+    ``attachment``, which asks the browser to offer the file to the user as a
+    download. Otherwise, a ``Content-Disposition`` header with a value of
+    ``inline`` (the browser default) will be set only if a filename is
+    available.
 
     If ``open_file`` doesn't have a name or if the name of ``open_file`` isn't
     appropriate, provide a custom file name using the ``filename``  parameter.
 
-    The ``Content-Length``, ``Content-Type``, and ``Content-Disposition``
-    headers are automatically set when they can be guessed from contents of
-    ``open_file``.
+    The ``Content-Length`` and ``Content-Type`` headers are automatically set
+    when they can be guessed from contents of ``open_file``.
 
 .. _wsgi.file_wrapper: https://www.python.org/dev/peps/pep-3333/#optional-platform-specific-file-handling
 
diff --git a/tests/responses/test_fileresponse.py b/tests/responses/test_fileresponse.py
index 5896373d4d..e77df4513a 100644
--- a/tests/responses/test_fileresponse.py
+++ b/tests/responses/test_fileresponse.py
@@ -14,12 +14,21 @@ class FileResponseTests(SimpleTestCase):
         response = FileResponse(open(__file__, 'rb'))
         self.assertEqual(response['Content-Length'], str(os.path.getsize(__file__)))
         self.assertIn(response['Content-Type'], ['text/x-python', 'text/plain'])
+        self.assertEqual(response['Content-Disposition'], 'inline; filename="test_fileresponse.py"')
         response.close()
 
     def test_file_from_buffer_response(self):
         response = FileResponse(io.BytesIO(b'binary content'))
         self.assertEqual(response['Content-Length'], '14')
         self.assertEqual(response['Content-Type'], 'application/octet-stream')
+        self.assertFalse(response.has_header('Content-Disposition'))
+        self.assertEqual(list(response), [b'binary content'])
+
+    def test_file_from_buffer_unnamed_attachment(self):
+        response = FileResponse(io.BytesIO(b'binary content'), as_attachment=True)
+        self.assertEqual(response['Content-Length'], '14')
+        self.assertEqual(response['Content-Type'], 'application/octet-stream')
+        self.assertEqual(response['Content-Disposition'], 'attachment')
         self.assertEqual(list(response), [b'binary content'])
 
     @skipIf(sys.platform == 'win32', "Named pipes are Unix-only.")