Spaces:
Build error
Build error
# 轻量级LaTeX处理器,适用于Hugging Face Spaces | |
FROM ubuntu:22.04 | |
# 设置环境变量 | |
ENV DEBIAN_FRONTEND=noninteractive | |
ENV TZ=Asia/Shanghai | |
ENV PYTHONUNBUFFERED=1 | |
# 安装系统依赖 | |
RUN apt-get update && apt-get install -y \ | |
# 基础工具 | |
curl \ | |
wget \ | |
git \ | |
unzip \ | |
# Python环境 | |
python3 \ | |
python3-pip \ | |
python3-venv \ | |
# LaTeX环境 | |
texlive-full \ | |
texlive-lang-chinese \ | |
texlive-xetex \ | |
texlive-luatex \ | |
# 字体支持 | |
fonts-noto-cjk \ | |
fonts-noto-cjk-extra \ | |
fonts-wqy-microhei \ | |
fonts-wqy-zenhei \ | |
# PDF工具 | |
poppler-utils \ | |
# 其他工具 | |
pandoc \ | |
imagemagick \ | |
&& rm -rf /var/lib/apt/lists/* | |
# 安装中文字体(基于教程中提到的字体) | |
RUN mkdir -p /usr/share/fonts/chinese | |
COPY fonts/ /usr/share/fonts/chinese/ 2>/dev/null || true | |
# 如果没有本地字体文件,下载一些常用中文字体 | |
RUN cd /usr/share/fonts/chinese && \ | |
# 下载思源字体 | |
wget -q https://github.com/adobe-fonts/source-han-sans/releases/download/2.004R/SourceHanSansCN.zip && \ | |
unzip -q SourceHanSansCN.zip && \ | |
rm SourceHanSansCN.zip && \ | |
# 更新字体缓存 | |
fc-cache -fv | |
# 设置工作目录 | |
WORKDIR /app | |
# 安装Python依赖 | |
RUN pip3 install --no-cache-dir \ | |
gradio \ | |
streamlit \ | |
fastapi \ | |
uvicorn \ | |
python-multipart \ | |
aiofiles \ | |
jinja2 \ | |
PyPDF2 \ | |
reportlab \ | |
matplotlib \ | |
pillow \ | |
numpy \ | |
pandas | |
# 创建应用目录结构 | |
RUN mkdir -p /app/templates \ | |
&& mkdir -p /app/uploads \ | |
&& mkdir -p /app/outputs \ | |
&& mkdir -p /app/temp | |
# 如果有本地requirements.txt,复制并安装 | |
COPY requirements.txt /app/ 2>/dev/null || echo "gradio" > /app/requirements.txt | |
RUN if [ -f /app/requirements.txt ]; then pip3 install --no-cache-dir -r /app/requirements.txt; fi | |
# 创建Python应用文件 | |
RUN python3 -c " | |
import os | |
app_code = '''import gradio as gr | |
import subprocess | |
import tempfile | |
import os | |
import shutil | |
from pathlib import Path | |
def compile_latex(latex_code, compiler=\"xelatex\"): | |
\"\"\"编译LaTeX代码并返回PDF\"\"\" | |
with tempfile.TemporaryDirectory() as temp_dir: | |
# 写入LaTeX文件 | |
tex_file = os.path.join(temp_dir, \"document.tex\") | |
with open(tex_file, \"w\", encoding=\"utf-8\") as f: | |
f.write(latex_code) | |
try: | |
# 编译LaTeX | |
result = subprocess.run( | |
[compiler, \"-interaction=nonstopmode\", \"-output-directory\", temp_dir, tex_file], | |
capture_output=True, | |
text=True, | |
timeout=30 | |
) | |
pdf_file = os.path.join(temp_dir, \"document.pdf\") | |
log_file = os.path.join(temp_dir, \"document.log\") | |
# 读取日志 | |
log_content = \"\" | |
if os.path.exists(log_file): | |
with open(log_file, \"r\", encoding=\"utf-8\", errors=\"ignore\") as f: | |
log_content = f.read() | |
if os.path.exists(pdf_file): | |
# 复制PDF到输出目录 | |
output_pdf = \"/app/outputs/output.pdf\" | |
shutil.copy2(pdf_file, output_pdf) | |
return output_pdf, f\"编译成功!\\n\\n编译日志:\\n{log_content}\" | |
else: | |
return None, f\"编译失败!\\n\\n错误信息:\\n{result.stderr}\\n\\n日志:\\n{log_content}\" | |
except subprocess.TimeoutExpired: | |
return None, \"编译超时(30秒)\" | |
except Exception as e: | |
return None, f\"编译出错: {str(e)}\" | |
# 创建Gradio界面 | |
def create_interface(): | |
with gr.Blocks(title=\"LaTeX编译器 - 支持中文\") as demo: | |
gr.Markdown(\"# LaTeX编译器(支持中文字体)\") | |
gr.Markdown(\"基于教程中的完整texlive环境,支持XeLaTeX编译中文文档\") | |
with gr.Row(): | |
with gr.Column(): | |
latex_input = gr.Textbox( | |
label=\"LaTeX代码\", | |
placeholder=\"请输入LaTeX代码...\", | |
lines=20, | |
value=\"\"\"\\\\documentclass{article} | |
\\\\usepackage{xeCJK} | |
\\\\setCJKmainfont{SimSun} | |
\\\\title{中文LaTeX示例} | |
\\\\author{作者姓名} | |
\\\\date{\\\\today} | |
\\\\begin{document} | |
\\\\maketitle | |
\\\\section{介绍} | |
这是一个支持中文的LaTeX文档示例。 | |
\\\\section{数学公式} | |
爱因斯坦的质能方程:$E = mc^2$ | |
\\\\end{document}\"\"\" | |
) | |
compiler = gr.Radio( | |
choices=[\"xelatex\", \"pdflatex\", \"lualatex\"], | |
value=\"xelatex\", | |
label=\"编译器选择\" | |
) | |
compile_btn = gr.Button(\"编译PDF\", variant=\"primary\") | |
with gr.Column(): | |
output_file = gr.File(label=\"生成的PDF\") | |
log_output = gr.Textbox(label=\"编译日志\", lines=15, interactive=False) | |
compile_btn.click( | |
fn=compile_latex, | |
inputs=[latex_input, compiler], | |
outputs=[output_file, log_output] | |
) | |
return demo | |
if __name__ == \"__main__\": | |
# 确保输出目录存在 | |
os.makedirs(\"/app/outputs\", exist_ok=True) | |
# 启动应用 | |
demo = create_interface() | |
demo.launch( | |
server_name=\"0.0.0.0\", | |
server_port=7860, | |
share=False | |
) | |
''' | |
with open('/app/app.py', 'w', encoding='utf-8') as f: | |
f.write(app_code) | |
" | |
# 设置权限 | |
RUN chmod +x /app/app.py | |
# 暴露端口 | |
EXPOSE 7860 | |
# 健康检查 | |
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | |
CMD curl -f http://localhost:7860/health || exit 1 | |
# 启动命令 | |
CMD ["python3", "/app/app.py"] |