Cleaner handling when preview generation fails. Using original file as fallback.
This commit is contained in:
+21
-13
@@ -13,7 +13,7 @@ import fitz # PyMuPDF
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pillow_heif
|
import pillow_heif
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from sanic import Blueprint, empty, raw
|
from sanic import Blueprint, empty, raw, redirect
|
||||||
from sanic.exceptions import NotFound
|
from sanic.exceptions import NotFound
|
||||||
from sanic.log import logger
|
from sanic.log import logger
|
||||||
|
|
||||||
@@ -43,12 +43,12 @@ async def preview(req, path):
|
|||||||
maxzoom = float(req.args.get("zoom", 2.0))
|
maxzoom = float(req.args.get("zoom", 2.0))
|
||||||
quality = int(req.args.get("q", 60))
|
quality = int(req.args.get("q", 60))
|
||||||
rel = PurePosixPath(sanitize(unquote(path)))
|
rel = PurePosixPath(sanitize(unquote(path)))
|
||||||
path = config.config.path / rel
|
filepath = config.config.path / rel
|
||||||
stat = path.lstat()
|
stat = filepath.lstat()
|
||||||
etag = config.derived_secret(
|
etag = config.derived_secret(
|
||||||
"preview", rel, stat.st_mtime_ns, quality, maxsize, maxzoom
|
"preview", rel, stat.st_mtime_ns, quality, maxsize, maxzoom
|
||||||
).hex()
|
).hex()
|
||||||
savename = PurePosixPath(path.name).with_suffix(".avif")
|
savename = PurePosixPath(filepath.name).with_suffix(".avif")
|
||||||
headers = {
|
headers = {
|
||||||
"etag": etag,
|
"etag": etag,
|
||||||
"last-modified": format_date_time(stat.st_mtime),
|
"last-modified": format_date_time(stat.st_mtime),
|
||||||
@@ -61,22 +61,30 @@ async def preview(req, path):
|
|||||||
# The client has it cached, respond 304 Not Modified
|
# The client has it cached, respond 304 Not Modified
|
||||||
return empty(304, headers=headers)
|
return empty(304, headers=headers)
|
||||||
|
|
||||||
if not path.is_file():
|
if not filepath.is_file():
|
||||||
raise NotFound("File not found")
|
raise NotFound("File not found")
|
||||||
|
|
||||||
img = await asyncio.get_event_loop().run_in_executor(
|
img = await asyncio.get_event_loop().run_in_executor(
|
||||||
req.app.ctx.threadexec, dispatch, path, quality, maxsize, maxzoom
|
req.app.ctx.threadexec, dispatch, filepath, quality, maxsize, maxzoom
|
||||||
)
|
)
|
||||||
|
if not img:
|
||||||
|
# Preview generation failed, redirect to the file itself
|
||||||
|
return redirect(f"/files/{path}", status=303)
|
||||||
return raw(img, headers=headers)
|
return raw(img, headers=headers)
|
||||||
|
|
||||||
|
|
||||||
def dispatch(path, quality, maxsize, maxzoom):
|
def dispatch(path, quality, maxsize, maxzoom):
|
||||||
if path.suffix.lower() in (".pdf", ".xps", ".epub", ".mobi"):
|
try:
|
||||||
return process_pdf(path, quality=quality, maxsize=maxsize, maxzoom=maxzoom)
|
if path.suffix.lower() in (".pdf", ".xps", ".epub", ".mobi"):
|
||||||
type, _ = mimetypes.guess_type(path.name)
|
return process_pdf(path, quality=quality, maxsize=maxsize, maxzoom=maxzoom)
|
||||||
if type and type.startswith("video/"):
|
type, _ = mimetypes.guess_type(path.name)
|
||||||
return process_video(path, quality=quality, maxsize=maxsize)
|
if type and type.startswith("video/"):
|
||||||
return process_image(path, quality=quality, maxsize=maxsize)
|
return process_video(path, quality=quality, maxsize=maxsize)
|
||||||
|
return process_image(path, quality=quality, maxsize=maxsize)
|
||||||
|
except ValueError as e:
|
||||||
|
logger.warning(f"Cannot generate preview for {path.name}: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Error generating preview for {path.name}: {e}")
|
||||||
|
|
||||||
|
|
||||||
def process_image(path, *, maxsize, quality):
|
def process_image(path, *, maxsize, quality):
|
||||||
@@ -121,7 +129,7 @@ def process_pdf(path, *, maxsize, maxzoom, quality, page_number=0):
|
|||||||
w, h = page.rect[2:4]
|
w, h = page.rect[2:4]
|
||||||
zoom = min(maxsize / w, maxsize / h, maxzoom)
|
zoom = min(maxsize / w, maxsize / h, maxzoom)
|
||||||
mat = fitz.Matrix(zoom, zoom)
|
mat = fitz.Matrix(zoom, zoom)
|
||||||
pix = page.get_pixmap(matrix=mat) # type: ignore[attr-defined]
|
pix = page.get_pixmap(matrix=mat)
|
||||||
t_load_end = perf_counter()
|
t_load_end = perf_counter()
|
||||||
|
|
||||||
t_save_start = perf_counter()
|
t_save_start = perf_counter()
|
||||||
|
|||||||
Reference in New Issue
Block a user