download cache

This commit is contained in:
Jörn-Michael Miehe 2022-08-31 10:41:36 +00:00
parent 21805b0d8a
commit 12959153c1
3 changed files with 46 additions and 10 deletions

View file

@ -1,8 +1,10 @@
import io import io
import logging import logging
import re import re
from typing import Iterator import time
from typing import Iterator, Optional
from async_lru import alru_cache
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from PIL import Image from PIL import Image
@ -66,6 +68,32 @@ async def find_images(
return list(file_names) return list(file_names)
async def get_ttl_hash(seconds: int = 20) -> int:
"""
Return the same value withing `seconds` time period
https://stackoverflow.com/a/55900800
"""
return round(time.time() / seconds)
@alru_cache(maxsize=20)
async def get_image_by_name(
file_name: str,
ttl_hash: Optional[int] = None,
) -> io.BytesIO:
del ttl_hash
file = DavFile(CLIENT.resource(f"img/{file_name}"), refresh=False)
print(f"Downloading {file_name}")
await file.download()
img = Image.open(io.BytesIO(file.bytes)).convert("RGB")
img_buffer = io.BytesIO()
img.save(img_buffer, format='JPEG', quality=85)
return img_buffer
@router.get( @router.get(
"/get/{prefix}", "/get/{prefix}",
responses={ responses={
@ -85,6 +113,7 @@ async def find_images(
async def get_image( async def get_image(
prefix: str, prefix: str,
file_names: Iterator[str] = Depends(find_file_names), file_names: Iterator[str] = Depends(find_file_names),
ttl_hash: int = Depends(get_ttl_hash),
) -> StreamingResponse: ) -> StreamingResponse:
file_names = list(file_names) file_names = list(file_names)
@ -94,17 +123,11 @@ async def get_image(
elif len(file_names) > 1: elif len(file_names) > 1:
raise HTTPException(status_code=status.HTTP_409_CONFLICT) raise HTTPException(status_code=status.HTTP_409_CONFLICT)
file_name = file_names[0] img_buffer = await get_image_by_name(file_names[0], ttl_hash)
file = DavFile(CLIENT.resource(f"img/{file_name}"), refresh=False)
await file.download()
img = Image.open(io.BytesIO(file.bytes)).convert("RGB")
img_buffer = io.BytesIO()
img.save(img_buffer, format='JPEG', quality=85)
img_buffer.seek(0) img_buffer.seek(0)
return StreamingResponse( return StreamingResponse(
img_buffer, content=img_buffer,
media_type="image/jpeg", media_type="image/jpeg",
headers={ headers={
"Content-Disposition": f"filename={prefix}.jpg" "Content-Disposition": f"filename={prefix}.jpg"

14
api/poetry.lock generated
View file

@ -41,6 +41,14 @@ tornado = ["tornado (>=4.3)"]
twisted = ["twisted"] twisted = ["twisted"]
zookeeper = ["kazoo"] zookeeper = ["kazoo"]
[[package]]
name = "async-lru"
version = "1.0.3"
description = "Simple lru_cache for asyncio"
category = "main"
optional = false
python-versions = ">=3.6"
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2022.6.15" version = "2022.6.15"
@ -363,7 +371,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "b39654ea53ee894dd65fe2217ca58fea259c9fe8a9bbae26f6198c42304608e2" content-hash = "04507c7951fd5d6a92767f82635087e15da2eff67f52e22e79b6e1db863e9ed4"
[metadata.files] [metadata.files]
anyio = [ anyio = [
@ -374,6 +382,10 @@ apscheduler = [
{file = "APScheduler-3.9.1-py2.py3-none-any.whl", hash = "sha256:ddc25a0ddd899de44d7f451f4375fb971887e65af51e41e5dcf681f59b8b2c9a"}, {file = "APScheduler-3.9.1-py2.py3-none-any.whl", hash = "sha256:ddc25a0ddd899de44d7f451f4375fb971887e65af51e41e5dcf681f59b8b2c9a"},
{file = "APScheduler-3.9.1.tar.gz", hash = "sha256:65e6574b6395498d371d045f2a8a7e4f7d50c6ad21ef7313d15b1c7cf20df1e3"}, {file = "APScheduler-3.9.1.tar.gz", hash = "sha256:65e6574b6395498d371d045f2a8a7e4f7d50c6ad21ef7313d15b1c7cf20df1e3"},
] ]
async-lru = [
{file = "async-lru-1.0.3.tar.gz", hash = "sha256:c2cb9b2915eb14e6cf3e717154b40f715bf90e596d73623677affd0d1fbcd32a"},
{file = "async_lru-1.0.3-py3-none-any.whl", hash = "sha256:ea692c303feb6211ff260d230dae1583636f13e05c9ae616eada77855b7f415c"},
]
certifi = [ certifi = [
{file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
{file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},

View file

@ -13,6 +13,7 @@ webdavclient3 = "3.14.5"
Markdown = "^3.4.1" Markdown = "^3.4.1"
APScheduler = "^3.9.1" APScheduler = "^3.9.1"
Pillow = "^9.2.0" Pillow = "^9.2.0"
async-lru = "^1.0.3"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
# pytest = "^5.2" # pytest = "^5.2"