Skip to content

Commit 659f6e9

Browse files
转
1 parent 0f1e6b7 commit 659f6e9

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

‎backend/Dockerfile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ WORKDIR /app
55
# Install system dependencies
66
RUN apt-get update && apt-get install -y \
77
libmagic1 \
8+
libheif1 \
89
&& rm -rf /var/lib/apt/lists/*
910

1011
# Copy requirements first for better caching

‎backend/app/services/file_service.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from sqlalchemy.ext.asyncio import AsyncSession
1212
from PIL import Image
1313
import magic
14+
from pillow_heif import register_heif_opener
1415

1516
from app.config import settings
1617
from app.models.file import File
@@ -22,6 +23,7 @@ def __init__(self, db: AsyncSession):
2223
self.db = db
2324
self.upload_dir = Path(settings.UPLOAD_DIR)
2425
self.upload_dir.mkdir(parents=True, exist_ok=True)
26+
register_heif_opener()
2527

2628
def _generate_share_token(self) -> str:
2729
"""生成唯一的分享 Token"""
@@ -109,6 +111,30 @@ async def file_iterator():
109111
while chunk := await f.read(8192):
110112
yield chunk
111113

114+
mime = (file_record.mime_type or "application/octet-stream").lower()
115+
# 浏览器对 HEIC/HEIF 支持很差:inline 时转码为 JPEG
116+
if inline and mime in ("image/heic", "image/heif"):
117+
async with aiofiles.open(file_path, "rb") as f:
118+
raw = await f.read()
119+
try:
120+
img = Image.open(BytesIO(raw))
121+
if img.mode in ("RGBA", "P"):
122+
img = img.convert("RGB")
123+
buffer = BytesIO()
124+
img.save(buffer, format="JPEG", quality=92, optimize=True)
125+
out = buffer.getvalue()
126+
return Response(
127+
content=out,
128+
media_type="image/jpeg",
129+
headers={
130+
"Content-Disposition": f'inline; filename="{Path(file_record.filename).stem}.jpg"',
131+
"Content-Length": str(len(out)),
132+
},
133+
)
134+
except Exception:
135+
# 转码失败则按原文件返回
136+
pass
137+
112138
disposition = "inline" if inline else "attachment"
113139
return StreamingResponse(
114140
file_iterator(),

‎backend/requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ email-validator==2.1.0
2424
aiofiles==23.2.1
2525
python-magic==0.4.27
2626
Pillow==10.2.0
27+
pillow-heif==0.16.0
2728

2829
# HTTP Client (for OAuth)
2930
httpx==0.26.0

0 commit comments

Comments
 (0)