mirror of
https://github.com/zulip/zulip.git
synced 2025-11-06 15:03:34 +00:00
thumbnail: Support checking for images from streaming sources.
We may not always have trivial access to all of the bytes of the uploaded file -- for instance, if the file was uploaded previously, or by some other process. Downloading the entire image in order to check its headers is an inefficient use of time and bandwidth. Adjust `maybe_thumbnail` and dependencies to potentially take a `pyvips.Source` which supports streaming data from S3 or disk. This allows making the ImageAttachment row, if deemed appropriate, based on only a few KB of data, and not the entire image.
This commit is contained in:
committed by
Tim Abbott
parent
758aa36cbe
commit
9a1f78db22
@@ -7,13 +7,14 @@ from collections.abc import Callable, Iterator
|
||||
from datetime import datetime
|
||||
from typing import IO, Any, BinaryIO, Literal
|
||||
|
||||
import pyvips
|
||||
from django.conf import settings
|
||||
from typing_extensions import override
|
||||
|
||||
from zerver.lib.mime_types import guess_type
|
||||
from zerver.lib.thumbnail import resize_avatar, resize_logo
|
||||
from zerver.lib.timestamp import timestamp_to_datetime
|
||||
from zerver.lib.upload.base import ZulipUploadBackend
|
||||
from zerver.lib.upload.base import StreamingSourceWithSize, ZulipUploadBackend
|
||||
from zerver.lib.utils import assert_is_not_none
|
||||
from zerver.models import Realm, RealmEmoji, UserProfile
|
||||
|
||||
@@ -100,6 +101,13 @@ class LocalUploadBackend(ZulipUploadBackend):
|
||||
def save_attachment_contents(self, path_id: str, filehandle: BinaryIO) -> None:
|
||||
filehandle.write(read_local_file("files", path_id))
|
||||
|
||||
@override
|
||||
def attachment_vips_source(self, path_id: str) -> StreamingSourceWithSize:
|
||||
file_path = os.path.join(assert_is_not_none(settings.LOCAL_UPLOADS_DIR), "files", path_id)
|
||||
assert_is_local_storage_path("files", file_path)
|
||||
source = pyvips.Source.new_from_file(file_path)
|
||||
return StreamingSourceWithSize(size=os.path.getsize(file_path), source=source)
|
||||
|
||||
@override
|
||||
def delete_message_attachment(self, path_id: str) -> bool:
|
||||
return delete_local_file("files", path_id)
|
||||
|
||||
Reference in New Issue
Block a user