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"] |