add:markdown 转 pdf
This commit is contained in:
@@ -58,6 +58,12 @@ from app.services.docling_adapter import (
|
||||
)
|
||||
from app.services.unified_converter import FormatConverter
|
||||
from app.services.minio_utils import minio_current, join_prefix, presigned_read
|
||||
from app.services.pdf_converter import (
|
||||
word_to_pdf_bytes,
|
||||
markdown_to_pdf_bytes,
|
||||
markdown_file_to_pdf_bytes,
|
||||
read_file_content,
|
||||
)
|
||||
|
||||
"""
|
||||
@api Server Application
|
||||
@@ -2561,6 +2567,193 @@ async def api_convert(
|
||||
except Exception as e:
|
||||
return _err(str(e))
|
||||
|
||||
@app.post("/api/pdf/convert")
|
||||
async def api_pdf_convert(
|
||||
file: Optional[UploadFile] = File(None),
|
||||
file_path: Optional[str] = Form(None),
|
||||
markdown_content: Optional[str] = Form(None),
|
||||
toc: bool = Form(False),
|
||||
header_text: Optional[str] = Form(None),
|
||||
footer_text: Optional[str] = Form(None),
|
||||
logo_url: Optional[str] = Form(None),
|
||||
copyright_text: Optional[str] = Form(None),
|
||||
filename_text: Optional[str] = Form(None),
|
||||
cover_src: Optional[str] = Form(None),
|
||||
product_name: Optional[str] = Form(None),
|
||||
document_name: Optional[str] = Form(None),
|
||||
product_version: Optional[str] = Form(None),
|
||||
document_version: Optional[str] = Form(None),
|
||||
css_name: Optional[str] = Form(None),
|
||||
css_text: Optional[str] = Form(None),
|
||||
download: bool = Form(True),
|
||||
):
|
||||
"""
|
||||
Convert Word or Markdown to PDF
|
||||
|
||||
Supports three input methods:
|
||||
1. Upload file (Word .doc/.docx or Markdown .md)
|
||||
2. Specify file_path (local file path)
|
||||
3. Provide markdown_content directly
|
||||
|
||||
Returns PDF file as download by default
|
||||
"""
|
||||
try:
|
||||
pdf_bytes: bytes = b""
|
||||
output_filename: str = "document.pdf"
|
||||
|
||||
# Determine input source
|
||||
if file:
|
||||
# Handle uploaded file
|
||||
filename = file.filename or "upload"
|
||||
suffix = Path(filename).suffix.lower()
|
||||
|
||||
# Save uploaded file to temp
|
||||
tmp_path = Path(tempfile.mktemp(suffix=suffix))
|
||||
try:
|
||||
content = await file.read()
|
||||
tmp_path.write_bytes(content)
|
||||
|
||||
if suffix in {".doc", ".docx"}:
|
||||
# Convert Word to PDF
|
||||
output_filename = f"{Path(filename).stem}.pdf"
|
||||
pdf_bytes = await asyncio.to_thread(
|
||||
word_to_pdf_bytes,
|
||||
tmp_path,
|
||||
toc=toc,
|
||||
header_text=header_text,
|
||||
footer_text=footer_text,
|
||||
logo_url=logo_url,
|
||||
copyright_text=copyright_text,
|
||||
filename_text=filename_text or Path(filename).stem,
|
||||
cover_src=cover_src,
|
||||
product_name=product_name,
|
||||
document_name=document_name,
|
||||
product_version=product_version,
|
||||
document_version=document_version,
|
||||
)
|
||||
elif suffix in {".md", ".markdown"}:
|
||||
# Convert Markdown file to PDF
|
||||
output_filename = f"{Path(filename).stem}.pdf"
|
||||
pdf_bytes = await asyncio.to_thread(
|
||||
markdown_file_to_pdf_bytes,
|
||||
tmp_path,
|
||||
toc=toc,
|
||||
header_text=header_text,
|
||||
footer_text=footer_text,
|
||||
logo_url=logo_url,
|
||||
copyright_text=copyright_text,
|
||||
filename_text=filename_text or Path(filename).stem,
|
||||
cover_src=cover_src,
|
||||
product_name=product_name,
|
||||
document_name=document_name,
|
||||
product_version=product_version,
|
||||
document_version=document_version,
|
||||
css_name=css_name,
|
||||
css_text=css_text,
|
||||
)
|
||||
else:
|
||||
return _err(f"不支持的文件格式: {suffix}。支持的格式: .doc, .docx, .md")
|
||||
finally:
|
||||
try:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
elif file_path:
|
||||
# Handle local file path
|
||||
path = Path(file_path).expanduser()
|
||||
if not path.exists():
|
||||
return _err(f"文件不存在: {file_path}")
|
||||
|
||||
suffix = path.suffix.lower()
|
||||
output_filename = f"{path.stem}.pdf"
|
||||
|
||||
if suffix in {".doc", ".docx"}:
|
||||
pdf_bytes = await asyncio.to_thread(
|
||||
word_to_pdf_bytes,
|
||||
path,
|
||||
toc=toc,
|
||||
header_text=header_text,
|
||||
footer_text=footer_text,
|
||||
logo_url=logo_url,
|
||||
copyright_text=copyright_text,
|
||||
filename_text=filename_text or path.stem,
|
||||
cover_src=cover_src,
|
||||
product_name=product_name,
|
||||
document_name=document_name,
|
||||
product_version=product_version,
|
||||
document_version=document_version,
|
||||
)
|
||||
elif suffix in {".md", ".markdown"}:
|
||||
pdf_bytes = await asyncio.to_thread(
|
||||
markdown_file_to_pdf_bytes,
|
||||
path,
|
||||
toc=toc,
|
||||
header_text=header_text,
|
||||
footer_text=footer_text,
|
||||
logo_url=logo_url,
|
||||
copyright_text=copyright_text,
|
||||
filename_text=filename_text or path.stem,
|
||||
cover_src=cover_src,
|
||||
product_name=product_name,
|
||||
document_name=document_name,
|
||||
product_version=product_version,
|
||||
document_version=document_version,
|
||||
css_name=css_name,
|
||||
css_text=css_text,
|
||||
)
|
||||
else:
|
||||
return _err(f"不支持的文件格式: {suffix}。支持的格式: .doc, .docx, .md")
|
||||
|
||||
elif markdown_content:
|
||||
# Handle direct markdown content
|
||||
output_filename = f"{filename_text or 'document'}.pdf"
|
||||
pdf_bytes = await asyncio.to_thread(
|
||||
markdown_to_pdf_bytes,
|
||||
markdown_content,
|
||||
toc=toc,
|
||||
header_text=header_text,
|
||||
footer_text=footer_text,
|
||||
logo_url=logo_url,
|
||||
copyright_text=copyright_text,
|
||||
filename_text=filename_text,
|
||||
cover_src=cover_src,
|
||||
product_name=product_name,
|
||||
document_name=document_name,
|
||||
product_version=product_version,
|
||||
document_version=document_version,
|
||||
css_name=css_name,
|
||||
css_text=css_text,
|
||||
)
|
||||
else:
|
||||
return _err("必须提供 file、file_path 或 markdown_content 中的一个")
|
||||
|
||||
if not pdf_bytes:
|
||||
return _err("PDF 转换失败,未生成内容")
|
||||
|
||||
# Return PDF file
|
||||
if download:
|
||||
from fastapi.responses import StreamingResponse
|
||||
return StreamingResponse(
|
||||
io.BytesIO(pdf_bytes),
|
||||
media_type="application/pdf",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename=\"{output_filename}\""
|
||||
}
|
||||
)
|
||||
else:
|
||||
# Return as base64 in JSON
|
||||
import base64
|
||||
return _ok({
|
||||
"pdf_base64": base64.b64encode(pdf_bytes).decode("ascii"),
|
||||
"filename": output_filename,
|
||||
"size": len(pdf_bytes)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logging.exception("PDF conversion error")
|
||||
return _err(f"PDF 转换失败: {str(e)}")
|
||||
|
||||
@app.post("/api/import/convert")
|
||||
async def api_import_convert(json_file: UploadFile = File(None), json_text: Optional[str] = Form(None), path: Optional[str] = Form(None), versionId: Optional[int] = Form(1001), download: Optional[bool] = Form(False)):
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user