Don't load temporary uploaded files into memory

These can be quite large. Instead pass them straight to Willow to have it read just as much as it needs to
pull/10310/head
Jake Howard 2023-03-10 12:00:46 +00:00 zatwierdzone przez Matt Westcott
rodzic 3c0c64642b
commit cfa11bbe00
2 zmienionych plików z 43 dodań i 5 usunięć

Wyświetl plik

@ -146,11 +146,11 @@ class WagtailImageField(ImageField):
if f is None:
return None
# We need to get a file object for Pillow. When we get a path, we need to open
# the file first. And we have to read the data into memory to pass to Willow.
# Get the file content ready for Willow
if hasattr(data, "temporary_file_path"):
with open(data.temporary_file_path(), "rb") as fh:
file = BytesIO(fh.read())
# Django's `TemporaryUploadedFile` is enough of a file to satisfy Willow
# Willow doesn't support opening images by path https://github.com/wagtail/Willow/issues/108
file = data
else:
if hasattr(data, "read"):
file = BytesIO(data.read())

Wyświetl plik

@ -3,7 +3,7 @@ import json
import urllib
from django.contrib.auth.models import Group, Permission
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files.uploadedfile import SimpleUploadedFile, TemporaryUploadedFile
from django.template.defaultfilters import filesizeformat
from django.template.loader import render_to_string
from django.test import RequestFactory, TestCase, override_settings
@ -567,6 +567,44 @@ class TestImageAddView(WagtailTestUtils, TestCase):
images = Image.objects.filter(title="Test image")
self.assertEqual(images.count(), 1)
def test_add_temporary_uploaded_file(self):
"""
Test that uploading large files (spooled to the filesystem) work as expected
"""
test_image_file = get_test_image_file()
uploaded_file = TemporaryUploadedFile(
"test.png", "image/png", test_image_file.size, "utf-8"
)
uploaded_file.write(test_image_file.file.getvalue())
uploaded_file.seek(0)
response = self.post(
{
"title": "Test image",
"file": uploaded_file,
}
)
# Should redirect back to index
self.assertRedirects(response, reverse("wagtailimages:index"))
# Check that the image was created
images = Image.objects.filter(title="Test image")
self.assertEqual(images.count(), 1)
# Test that size was populated correctly
image = images.first()
self.assertEqual(image.width, 640)
self.assertEqual(image.height, 480)
# Test that the file_size/hash fields were set
self.assertTrue(image.file_size)
self.assertTrue(image.file_hash)
# Test that it was placed in the root collection
root_collection = Collection.get_first_root_node()
self.assertEqual(image.collection, root_collection)
@override_settings(
DEFAULT_FILE_STORAGE="wagtail.test.dummy_external_storage.DummyExternalStorage"
)