Compare commits

...

4 Commits

Author SHA1 Message Date
Trenton H
12dc3c57b2 Set Content-Length directly, Django isn't guessing it 2025-03-14 09:45:23 -07:00
Trenton H
a173f05d89 Account for the streaming nature 2025-03-14 08:57:38 -07:00
Trenton H
979af82989 Use right args and call 2025-03-14 08:57:38 -07:00
Trenton H
1b4e44d965 Investigate using more precise response 2025-03-14 08:57:37 -07:00
2 changed files with 18 additions and 20 deletions

View File

@ -68,7 +68,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 2) self.assertEqual(len(zipf.filelist), 2)
self.assertIn("2021-01-01 document A.pdf", zipf.namelist()) self.assertIn("2021-01-01 document A.pdf", zipf.namelist())
self.assertIn("2020-03-21 document B.jpg", zipf.namelist()) self.assertIn("2020-03-21 document B.jpg", zipf.namelist())
@ -89,7 +89,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 2) self.assertEqual(len(zipf.filelist), 2)
self.assertIn("2021-01-01 document A.pdf", zipf.namelist()) self.assertIn("2021-01-01 document A.pdf", zipf.namelist())
self.assertIn("2020-03-21 document B.pdf", zipf.namelist()) self.assertIn("2020-03-21 document B.pdf", zipf.namelist())
@ -110,7 +110,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 3) self.assertEqual(len(zipf.filelist), 3)
self.assertIn("originals/2021-01-01 document A.pdf", zipf.namelist()) self.assertIn("originals/2021-01-01 document A.pdf", zipf.namelist())
self.assertIn("archive/2020-03-21 document B.pdf", zipf.namelist()) self.assertIn("archive/2020-03-21 document B.pdf", zipf.namelist())
@ -144,7 +144,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 2) self.assertEqual(len(zipf.filelist), 2)
self.assertIn("2021-01-01 document A.pdf", zipf.namelist()) self.assertIn("2021-01-01 document A.pdf", zipf.namelist())
@ -203,7 +203,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 2) self.assertEqual(len(zipf.filelist), 2)
self.assertIn("a space name/Title 2 - Doc 3.jpg", zipf.namelist()) self.assertIn("a space name/Title 2 - Doc 3.jpg", zipf.namelist())
self.assertIn("test/This is Doc 2.pdf", zipf.namelist()) self.assertIn("test/This is Doc 2.pdf", zipf.namelist())
@ -249,7 +249,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 2) self.assertEqual(len(zipf.filelist), 2)
self.assertIn("somewhere/This is Doc 2.pdf", zipf.namelist()) self.assertIn("somewhere/This is Doc 2.pdf", zipf.namelist())
self.assertIn("somewhere/Title 2 - Doc 3.pdf", zipf.namelist()) self.assertIn("somewhere/Title 2 - Doc 3.pdf", zipf.namelist())
@ -298,7 +298,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response["Content-Type"], "application/zip") self.assertEqual(response["Content-Type"], "application/zip")
with zipfile.ZipFile(io.BytesIO(response.content)) as zipf: with zipfile.ZipFile(io.BytesIO(response.getvalue())) as zipf:
self.assertEqual(len(zipf.filelist), 3) self.assertEqual(len(zipf.filelist), 3)
self.assertIn("originals/bill/This is Doc 2.pdf", zipf.namelist()) self.assertIn("originals/bill/This is Doc 2.pdf", zipf.namelist())
self.assertIn("archive/statement/Title 2 - Doc 3.pdf", zipf.namelist()) self.assertIn("archive/statement/Title 2 - Doc 3.pdf", zipf.namelist())

View File

@ -32,6 +32,7 @@ from django.db.models import When
from django.db.models.functions import Length from django.db.models.functions import Length
from django.db.models.functions import Lower from django.db.models.functions import Lower
from django.db.models.manager import Manager from django.db.models.manager import Manager
from django.http import FileResponse
from django.http import Http404 from django.http import Http404
from django.http import HttpResponse from django.http import HttpResponse
from django.http import HttpResponseBadRequest from django.http import HttpResponseBadRequest
@ -2015,10 +2016,10 @@ class BulkDownloadView(GenericAPIView):
return HttpResponseForbidden("Insufficient permissions") return HttpResponseForbidden("Insufficient permissions")
settings.SCRATCH_DIR.mkdir(parents=True, exist_ok=True) settings.SCRATCH_DIR.mkdir(parents=True, exist_ok=True)
temp = tempfile.NamedTemporaryFile( # noqa: SIM115 temp_dir = Path(
dir=settings.SCRATCH_DIR, tempfile.mkdtemp(
suffix="-compressed-archive", dir=settings.SCRATCH_DIR,
delete=False, ),
) )
if content == "both": if content == "both":
@ -2028,20 +2029,17 @@ class BulkDownloadView(GenericAPIView):
else: else:
strategy_class = ArchiveOnlyStrategy strategy_class = ArchiveOnlyStrategy
with zipfile.ZipFile(temp.name, "w", compression) as zipf: zip_file = temp_dir / "documents.zip"
with zipfile.ZipFile(zip_file, "w", compression) as zipf:
strategy = strategy_class(zipf, follow_formatting=follow_filename_format) strategy = strategy_class(zipf, follow_formatting=follow_filename_format)
for document in documents: for document in documents:
strategy.add_document(document) strategy.add_document(document)
# TODO(stumpylog): Investigate using FileResponse here response = FileResponse(zip_file.open("rb"), as_attachment=True)
with open(temp.name, "rb") as f: response["Content-Length"] = zip_file.stat().st_size
response = HttpResponse(f, content_type="application/zip")
response["Content-Disposition"] = '{}; filename="{}"'.format(
"attachment",
"documents.zip",
)
return response return response
@extend_schema_view(**generate_object_with_permissions_schema(StoragePathSerializer)) @extend_schema_view(**generate_object_with_permissions_schema(StoragePathSerializer))