test_fileresponse.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import io
  2. import os
  3. import sys
  4. import tempfile
  5. from unittest import skipIf
  6. from django.core.files.base import ContentFile
  7. from django.http import FileResponse
  8. from django.test import SimpleTestCase
  9. class FileResponseTests(SimpleTestCase):
  10. def test_file_from_disk_response(self):
  11. response = FileResponse(open(__file__, 'rb'))
  12. self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__)))
  13. self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain'])
  14. self.assertEqual(
  15. response.headers['Content-Disposition'],
  16. 'inline; filename="test_fileresponse.py"',
  17. )
  18. response.close()
  19. def test_file_from_buffer_response(self):
  20. response = FileResponse(io.BytesIO(b'binary content'))
  21. self.assertEqual(response.headers['Content-Length'], '14')
  22. self.assertEqual(response.headers['Content-Type'], 'application/octet-stream')
  23. self.assertFalse(response.has_header('Content-Disposition'))
  24. self.assertEqual(list(response), [b'binary content'])
  25. def test_file_from_buffer_unnamed_attachment(self):
  26. response = FileResponse(io.BytesIO(b'binary content'), as_attachment=True)
  27. self.assertEqual(response.headers['Content-Length'], '14')
  28. self.assertEqual(response.headers['Content-Type'], 'application/octet-stream')
  29. self.assertEqual(response.headers['Content-Disposition'], 'attachment')
  30. self.assertEqual(list(response), [b'binary content'])
  31. @skipIf(sys.platform == 'win32', "Named pipes are Unix-only.")
  32. def test_file_from_named_pipe_response(self):
  33. with tempfile.TemporaryDirectory() as temp_dir:
  34. pipe_file = os.path.join(temp_dir, 'named_pipe')
  35. os.mkfifo(pipe_file)
  36. pipe_for_read = os.open(pipe_file, os.O_RDONLY | os.O_NONBLOCK)
  37. with open(pipe_file, 'wb') as pipe_for_write:
  38. pipe_for_write.write(b'binary content')
  39. response = FileResponse(os.fdopen(pipe_for_read, mode='rb'))
  40. self.assertEqual(list(response), [b'binary content'])
  41. response.close()
  42. self.assertFalse(response.has_header('Content-Length'))
  43. def test_file_from_disk_as_attachment(self):
  44. response = FileResponse(open(__file__, 'rb'), as_attachment=True)
  45. self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__)))
  46. self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain'])
  47. self.assertEqual(
  48. response.headers['Content-Disposition'],
  49. 'attachment; filename="test_fileresponse.py"',
  50. )
  51. response.close()
  52. def test_compressed_response(self):
  53. """
  54. If compressed responses are served with the uncompressed Content-Type
  55. and a compression Content-Encoding, browsers might automatically
  56. uncompress the file, which is most probably not wanted.
  57. """
  58. test_tuples = (
  59. ('.tar.gz', 'application/gzip'),
  60. ('.tar.bz2', 'application/x-bzip'),
  61. ('.tar.xz', 'application/x-xz'),
  62. )
  63. for extension, mimetype in test_tuples:
  64. with self.subTest(ext=extension):
  65. with tempfile.NamedTemporaryFile(suffix=extension) as tmp:
  66. response = FileResponse(tmp)
  67. self.assertEqual(response.headers['Content-Type'], mimetype)
  68. self.assertFalse(response.has_header('Content-Encoding'))
  69. def test_unicode_attachment(self):
  70. response = FileResponse(
  71. ContentFile(b'binary content', name="祝您平安.odt"), as_attachment=True,
  72. content_type='application/vnd.oasis.opendocument.text',
  73. )
  74. self.assertEqual(
  75. response.headers['Content-Type'],
  76. 'application/vnd.oasis.opendocument.text',
  77. )
  78. self.assertEqual(
  79. response.headers['Content-Disposition'],
  80. "attachment; filename*=utf-8''%E7%A5%9D%E6%82%A8%E5%B9%B3%E5%AE%89.odt"
  81. )