fix excel webp mimetype registration for openpyxl
This commit is contained in:
parent
629a520201
commit
c382665753
@ -7,6 +7,7 @@ import mimetypes
|
||||
import re
|
||||
import ssl
|
||||
import tempfile
|
||||
import zipfile
|
||||
import urllib.error
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
@ -16,6 +17,7 @@ from typing import Iterable
|
||||
|
||||
from openpyxl import load_workbook
|
||||
from openpyxl.drawing.image import Image as XLImage
|
||||
from openpyxl.packaging import manifest as openpyxl_manifest
|
||||
from openpyxl.utils import column_index_from_string, get_column_letter
|
||||
try:
|
||||
from PIL import Image as PILImage
|
||||
@ -44,8 +46,98 @@ IMAGE_HINT_HEADERS = (
|
||||
"image url",
|
||||
"图片",
|
||||
)
|
||||
mimetypes.add_type("image/webp", ".webp", strict=True)
|
||||
mimetypes.add_type("image/webp", ".webp", strict=False)
|
||||
|
||||
|
||||
def _iter_mimetype_modules():
|
||||
yield mimetypes
|
||||
compat = getattr(openpyxl_manifest, "mimetypes", None)
|
||||
if compat is not None:
|
||||
yield compat
|
||||
|
||||
|
||||
def _resolve_type_maps(module) -> tuple[dict, dict]:
|
||||
type_maps = getattr(module, "types_map", {})
|
||||
if isinstance(type_maps, tuple) and len(type_maps) >= 2:
|
||||
loose_map, strict_map = type_maps[0], type_maps[1]
|
||||
if isinstance(strict_map, dict) and isinstance(loose_map, dict):
|
||||
return strict_map, loose_map
|
||||
if (
|
||||
isinstance(type_maps, dict)
|
||||
and isinstance(type_maps.get(True), dict)
|
||||
and isinstance(type_maps.get(False), dict)
|
||||
):
|
||||
return type_maps[True], type_maps[False]
|
||||
if isinstance(type_maps, dict):
|
||||
loose_map = getattr(module, "common_types", {})
|
||||
if not isinstance(loose_map, dict):
|
||||
loose_map = type_maps
|
||||
return type_maps, loose_map
|
||||
return {}, {}
|
||||
|
||||
|
||||
def _register_type(module, extension: str, mime_type: str) -> None:
|
||||
add_type = getattr(module, "add_type", None)
|
||||
if callable(add_type):
|
||||
try:
|
||||
add_type(mime_type, extension, strict=True)
|
||||
except TypeError:
|
||||
try:
|
||||
add_type(mime_type, extension)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
add_type(mime_type, extension, strict=False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
strict_map, loose_map = _resolve_type_maps(module)
|
||||
strict_map[extension] = mime_type
|
||||
loose_map.setdefault(extension, mime_type)
|
||||
|
||||
|
||||
def ensure_mimetype_for_ext(ext: str) -> None:
|
||||
normalized_raw = str(ext or "").strip()
|
||||
if not normalized_raw:
|
||||
return
|
||||
|
||||
if not normalized_raw.startswith("."):
|
||||
normalized_raw = f".{normalized_raw}"
|
||||
normalized = normalized_raw.lower()
|
||||
|
||||
guessed = mimetypes.types_map.get(normalized)
|
||||
if not guessed:
|
||||
guessed = mimetypes.common_types.get(normalized)
|
||||
if not guessed:
|
||||
guessed, _ = mimetypes.guess_type(f"x{normalized}", strict=False)
|
||||
if not guessed and normalized in {".webp", ".WEBP"}:
|
||||
guessed = "image/webp"
|
||||
if not guessed:
|
||||
guessed = "application/octet-stream"
|
||||
|
||||
variants = {normalized}
|
||||
variants.add(normalized_raw)
|
||||
if normalized_raw != normalized:
|
||||
variants.add(normalized_raw.upper())
|
||||
|
||||
for module in _iter_mimetype_modules():
|
||||
for variant in variants:
|
||||
_register_type(module, variant, guessed)
|
||||
|
||||
|
||||
ensure_mimetype_for_ext(".webp")
|
||||
|
||||
|
||||
def register_mimetypes_from_archive(path: Path) -> None:
|
||||
try:
|
||||
with zipfile.ZipFile(path, "r") as archive:
|
||||
for name in archive.namelist():
|
||||
suffix = Path(name).suffix
|
||||
if suffix:
|
||||
ensure_mimetype_for_ext(suffix)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -247,6 +339,7 @@ def download_image(url: str, timeout: int, ssl_context):
|
||||
|
||||
def to_excel_safe_image(payload: bytes, extension: str) -> tuple[bytes, str]:
|
||||
ext = (extension or "").lower()
|
||||
ensure_mimetype_for_ext(ext)
|
||||
if ext in EXCEL_SAFE_EXTENSIONS and ext not in UNSAFE_OR_UNKNOWN_EXTENSIONS:
|
||||
return payload, ext
|
||||
|
||||
@ -367,6 +460,7 @@ def main() -> int:
|
||||
print(f"ERROR: input does not exist: {input_path}")
|
||||
return 1
|
||||
|
||||
register_mimetypes_from_archive(input_path)
|
||||
ssl_context = build_ssl_context(args.skip_tls_verify)
|
||||
|
||||
workbook = load_workbook(input_path)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user