10 KiB
10 KiB
Word/Markdown 转 PDF API 使用指南
API 端点
POST /api/pdf/convert
支持的输入方式
1. 上传文件
支持上传 .doc, .docx, .md 文件:
// 上传 Word 文件
const formData = new FormData();
formData.append('file', fileInput.files[0]); // .doc 或 .docx
// 可选参数
formData.append('toc', 'true'); // 生成目录
formData.append('header_text', '文档标题|页码'); // 页眉
formData.append('footer_text', '版权信息'); // 页脚
formData.append('filename_text', '我的文档'); // 文件名
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
const blob = await response.blob();
const url = URL.createObjectURL(blob);
2. 指定本地文件路径
const formData = new FormData();
formData.append('file_path', '/path/to/document.docx');
formData.append('toc', 'true');
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
3. 直接提交 Markdown 内容
const formData = new FormData();
formData.append('markdown_content', '# 标题\n\n这是内容');
formData.append('filename_text', '我的文档');
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
完整参数列表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | File | 否* | 上传的文件 |
| file_path | string | 否* | 本地文件路径 |
| markdown_content | string | 否* | Markdown 内容 |
| toc | boolean | 否 | 是否生成目录,默认 false |
| header_text | string | 否 | 页眉文本,可用 | 分隔左右 |
| footer_text | string | 否 | 页脚文本 |
| logo_url | string | 否 | Logo 图片 URL |
| copyright_text | string | 否 | 版权声明 |
| filename_text | string | 否 | 显示的文件名 |
| cover_src | string | 否 | 封面图片 URL |
| product_name | string | 否 | 产品名称(封面) |
| document_name | string | 否 | 文档名称(封面) |
| product_version | string | 否 | 产品版本 |
| document_version | string | 否 | 文档版本 |
| css_name | string | 否 | CSS 样式名称 |
| css_text | string | 否 | 自定义 CSS |
| download | boolean | 否 | 是否直接下载,默认 true |
*注:file、file_path、markdown_content 三者必选其一
完整示例代码
React 示例
import { useState, useRef } from 'react';
function PdfConverter() {
const [loading, setLoading] = useState(false);
const fileInput = useRef(null);
const convertToPdf = async () => {
const file = fileInput.current.files[0];
if (!file) return;
setLoading(true);
const formData = new FormData();
formData.append('file', file);
formData.append('toc', 'true');
formData.append('header_text', '我的文档|第 {page} 页');
formData.append('footer_text', '© 2024 公司名称');
formData.append('filename_text', file.name.replace(/\.[^/.]+$/, ''));
try {
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || '转换失败');
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
// 下载 PDF
const a = document.createElement('a');
a.href = url;
a.download = file.name.replace(/\.[^/.]+$/, '') + '.pdf';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
console.error('转换失败:', error);
alert('转换失败: ' + error.message);
} finally {
setLoading(false);
}
};
return (
<div>
<input
type="file"
ref={fileInput}
accept=".doc,.docx,.md"
/>
<button
onClick={convertToPdf}
disabled={loading}
>
{loading ? '转换中...' : '转换为 PDF'}
</button>
</div>
);
}
Vue 3 示例
<template>
<div>
<input
ref="fileInput"
type="file"
accept=".doc,.docx,.md"
/>
<button
@click="convertToPdf"
:disabled="loading"
>
{{ loading ? '转换中...' : '转换为 PDF' }}
</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const fileInput = ref(null);
const loading = ref(false);
const convertToPdf = async () => {
const file = fileInput.value.files[0];
if (!file) return;
loading.value = true;
const formData = new FormData();
formData.append('file', file);
formData.append('toc', 'true');
formData.append('header_text', '我的文档');
formData.append('filename_text', file.name.replace(/\.[^/.]+$/, ''));
try {
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || '转换失败');
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.name.replace(/\.[^/.]+$/, '') + '.pdf';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
console.error('转换失败:', error);
alert('转换失败: ' + error.message);
} finally {
loading.value = false;
}
};
</script>
原生 JavaScript 示例
<!DOCTYPE html>
<html>
<head>
<title>Word/Markdown 转 PDF</title>
</head>
<body>
<h1>文档转 PDF</h1>
<input type="file" id="fileInput" accept=".doc,.docx,.md">
<button id="convertBtn">转换为 PDF</button>
<div id="status" style="margin-top: 10px;"></div>
<script>
document.getElementById('convertBtn').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
const status = document.getElementById('status');
const file = fileInput.files[0];
if (!file) {
status.textContent = '请选择文件';
return;
}
status.textContent = '转换中...';
const formData = new FormData();
formData.append('file', file);
formData.append('toc', 'true');
formData.append('header_text', '我的文档|{page}');
formData.append('footer_text', '© 2024');
formData.append('filename_text', file.name.replace(/\.[^/.]+$/, ''));
try {
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || '转换失败');
}
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.name.replace(/\.[^/.]+$/, '') + '.pdf';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
status.textContent = '转换成功!';
} catch (error) {
console.error(error);
status.textContent = '转换失败: ' + error.message;
}
});
</script>
</body>
</html>
Markdown 内容转 PDF 示例
async function markdownToPdf() {
const markdownContent = `
# 我的文档
## 第一章
这是第一章的内容。
### 小节
- 列表项 1
- 列表项 2
| 列1 | 列2 |
|-----|-----|
| A | B |
`;
const formData = new FormData();
formData.append('markdown_content', markdownContent);
formData.append('filename_text', '我的Markdown文档');
formData.append('toc', 'true');
formData.append('header_text', 'Markdown文档');
formData.append('footer_text', '© 2024');
const response = await fetch('/api/pdf/convert', {
method: 'POST',
body: formData
});
const blob = await response.blob();
// 保存 PDF
saveAs(blob, 'document.pdf');
}
Python 调用示例
import requests
def convert_word_to_pdf(file_path, output_path):
"""将 Word 文件转换为 PDF"""
with open(file_path, 'rb') as f:
files = {'file': f}
data = {
'toc': 'true',
'header_text': '我的文档',
'footer_text': '© 2024',
'filename_text': '文档名称'
}
response = requests.post(
'http://localhost:8000/api/pdf/convert',
files=files,
data=data
)
if response.status_code == 200:
with open(output_path, 'wb') as out:
out.write(response.content)
print(f"PDF 已保存到: {output_path}")
else:
print(f"转换失败: {response.text}")
# 使用示例
convert_word_to_pdf('document.docx', 'output.pdf')
cURL 示例
# 上传 Word 文件转 PDF
curl -X POST http://localhost:8000/api/pdf/convert \
-F "file=@document.docx" \
-F "toc=true" \
-F "header_text=我的文档" \
-F "footer_text=© 2024" \
-o output.pdf
# Markdown 内容转 PDF
curl -X POST http://localhost:8000/api/pdf/convert \
-F "markdown_content=# 标题\n\n这是内容" \
-F "filename_text=文档" \
-o output.pdf
错误处理
API 返回的错误格式:
{
"detail": "错误信息"
}
常见错误:
| 错误信息 | 原因 | 解决方法 |
|---|---|---|
| 必须提供 file、file_path 或 markdown_content 中的一个 | 未提供输入 | 检查请求参数 |
| 不支持的文件格式 | 文件格式错误 | 确保是 .doc/.docx/.md |
| 文件不存在 | 本地文件路径无效 | 检查 file_path 参数 |
| PDF 转换失败 | 转换过程出错 | 查看服务器日志 |
返回格式
download=true (默认)
直接返回 PDF 文件流:
Content-Type: application/pdf
Content-Disposition: attachment; filename="document.pdf"
download=false
返回 JSON,包含 base64 编码的 PDF:
{
"ok": true,
"pdf_base64": "JVBERi0xLjQK...",
"filename": "document.pdf",
"size": 12345
}