/api/msd/read: zstd supported

This commit is contained in:
Maxim Devaev 2022-08-14 21:03:45 +03:00
parent de6fd94349
commit 4f9501a806
3 changed files with 41 additions and 22 deletions

View File

@ -60,6 +60,7 @@ depends=(
python-hidapi python-hidapi
python-six python-six
python-pyrad python-pyrad
python-zstandard
libgpiod libgpiod
freetype2 freetype2
"v4l-utils>=1.22.1-1" "v4l-utils>=1.22.1-1"

View File

@ -29,6 +29,7 @@ from typing import Optional
from typing import Union from typing import Union
import aiohttp import aiohttp
import zstandard
from aiohttp.web import Request from aiohttp.web import Request
from aiohttp.web import Response from aiohttp.web import Response
@ -48,6 +49,7 @@ from ....htserver import stream_json_exception
from ....plugins.msd import BaseMsd from ....plugins.msd import BaseMsd
from ....validators import check_string_in_list
from ....validators.basic import valid_bool from ....validators.basic import valid_bool
from ....validators.basic import valid_int_f0 from ....validators.basic import valid_int_f0
from ....validators.basic import valid_float_f01 from ....validators.basic import valid_float_f01
@ -90,34 +92,49 @@ class MsdApi:
@exposed_http("GET", "/msd/read") @exposed_http("GET", "/msd/read")
async def __read_handler(self, request: Request) -> StreamResponse: async def __read_handler(self, request: Request) -> StreamResponse:
name = valid_msd_image_name(request.query.get("image")) name = valid_msd_image_name(request.query.get("image"))
compress = valid_bool(request.query.get("compress", False)) compressors = {
async with self.__msd.read_image(name) as reader: "": ("", None),
size = reader.get_total_size() "none": ("", None),
src = reader.read_chunked() "lzma": (".xz", (lambda: lzma.LZMACompressor())), # pylint: disable=unnecessary-lambda
if compress: "zstd": (".zst", (lambda: zstandard.ZstdCompressor().compressobj())), # pylint: disable=unnecessary-lambda
name += ".xz" }
size = -1 (suffix, make_compressor) = compressors[check_string_in_list(
src = self.__compressed(reader.get_chunk_size(), src) arg=request.query.get("compress", ""),
response = await start_streaming(request, "application/octet-stream", size, name) name="Compression mode",
async for chunk in src: variants=set(compressors),
await response.write(chunk) )]
return response
async def __compressed(self, limit: int, src: AsyncGenerator[bytes, None]) -> AsyncGenerator[bytes, None]: async with self.__msd.read_image(name) as reader:
if make_compressor is None:
src = reader.read_chunked()
size = reader.get_total_size()
else:
async def compressed() -> AsyncGenerator[bytes, None]:
assert make_compressor is not None
compressor = make_compressor() # pylint: disable=not-callable
limit = reader.get_chunk_size()
buf = b"" buf = b""
xz = lzma.LZMACompressor()
try: try:
async for chunk in src: async for chunk in reader.read_chunked():
buf += await aiotools.run_async(xz.compress, chunk) buf += await aiotools.run_async(compressor.compress, chunk)
if len(buf) >= limit: if len(buf) >= limit:
yield buf yield buf
buf = b"" buf = b""
finally: finally:
# Закрыть в любом случае # Закрыть в любом случае
buf += await aiotools.run_async(xz.flush) buf += await aiotools.run_async(compressor.flush)
if len(buf) > 0: if len(buf) > 0:
yield buf yield buf
src = compressed()
size = -1
response = await start_streaming(request, "application/octet-stream", size, name + suffix)
async for chunk in src:
await response.write(chunk)
return response
# ===== # =====
@exposed_http("POST", "/msd/write") @exposed_http("POST", "/msd/write")

View File

@ -51,6 +51,7 @@ RUN pacman --noconfirm --ask=4 -Syy \
python-pillow \ python-pillow \
python-xlib \ python-xlib \
python-hidapi \ python-hidapi \
python-zstandard \
freetype2 \ freetype2 \
nginx-mainline \ nginx-mainline \
tesseract \ tesseract \