PPTX-to-PDF-Linux / pptx2pdf_web_en.py
innoai's picture
Upload pptx2pdf_web_en.py
6156ecf verified
import gradio as gr
import os
import shutil
import subprocess
import sys
import tempfile
from zipfile import ZipFile
from pathlib import Path
# 程序根目录
BASE_DIR = os.path.dirname(__file__)
# 可执行文件路径:根据操作系统确定
if sys.platform.startswith('win'):
BINARY_PATH = os.path.join(BASE_DIR, "PptxToPDF.exe")
else:
BINARY_PATH = os.path.join(BASE_DIR, "PptxToPDF")
# 启动时确保二进制有执行权限(在 Hugging Face Spaces 里无法手动 chmod)
try:
if not sys.platform.startswith('win'):
os.chmod(BINARY_PATH, 0o755)
except Exception as e:
# 如果权限设置失败,也无需中断,只要后续能调用即可
print(f"⚠️ 警告:设置执行权限失败:{e}")
def install_fonts_from_repository():
"""
将仓库中的 fonts 目录下的所有字体文件复制到 ~/.fonts 目录,并刷新字体缓存。
"""
try:
# 获取当前用户的主目录路径
home_dir = Path.home()
# 定义目标字体目录路径:~/.fonts
fonts_dir = home_dir / ".fonts"
# 如果 ~/.fonts 目录不存在,则创建该目录
if not fonts_dir.exists():
fonts_dir.mkdir(parents=True)
print(f"已创建字体目录:{fonts_dir}")
else:
print(f"字体目录已存在:{fonts_dir}")
# 定义仓库中的 fonts 目录路径
repo_fonts_dir = Path(__file__).parent / "fonts"
# 检查仓库中的 fonts 目录是否存在
if not repo_fonts_dir.exists():
print(f"错误:仓库中的 fonts 目录不存在:{repo_fonts_dir}")
return
# 支持的字体文件扩展名
font_extensions = [".ttf", ".otf", ".ttc"]
# 统计已复制的字体文件数量
copied_count = 0
# 遍历 fonts 目录中的所有文件
for font_file in repo_fonts_dir.iterdir():
if font_file.suffix.lower() in font_extensions:
destination = fonts_dir / font_file.name
try:
shutil.copy(font_file, destination)
print(f"已复制字体文件:{font_file.name}{destination}")
copied_count += 1
except Exception as e:
print(f"复制字体文件时出错:{font_file.name},错误信息:{e}")
if copied_count == 0:
print("未找到任何可复制的字体文件。")
return
# 刷新字体缓存(仅在 Linux/Mac 下)
if not sys.platform.startswith('win'):
try:
print("正在刷新字体缓存...")
subprocess.run(["fc-cache", "-f", "-v"], check=True)
print("字体缓存刷新完成。")
except subprocess.CalledProcessError as e:
print(f"刷新字体缓存时出错:{e}")
except Exception as e:
print(f"安装字体时出错:{e}")
# 启动时安装字体
install_fonts_from_repository()
def convert_pptx_to_pdf(pptx_path, output_dir):
# 检查可执行文件是否存在
if not os.path.exists(BINARY_PATH):
raise FileNotFoundError(f"PptxToPDF 可执行文件未找到: {BINARY_PATH}")
pdf_path = os.path.join(output_dir, os.path.splitext(os.path.basename(pptx_path))[0] + ".pdf")
result = subprocess.run([
BINARY_PATH,
pptx_path
], cwd=output_dir, capture_output=True, text=True)
if result.returncode != 0 or not os.path.exists(pdf_path):
raise RuntimeError(f"Conversion failed: {result.stderr}")
return pdf_path
def make_zip_file(files, zip_path):
with ZipFile(zip_path, 'w') as zipf:
for f in files:
zipf.write(f, os.path.basename(f))
return zip_path
def pptx2pdf_web(pptx_file): # pptx_file is the Gradio file object
# Create a temporary directory that won't be auto-deleted
tmpdir = tempfile.mkdtemp()
try:
gradio_temp_file_path = pptx_file.name # Path to the file uploaded by Gradio
# Create a path for our copy of the PPTX inside our own tmpdir
# Use the original basename of the uploaded file
target_pptx_filename = os.path.basename(gradio_temp_file_path)
our_copy_of_pptx_path = os.path.join(tmpdir, target_pptx_filename)
# Copy the uploaded PPTX from Gradio's temp location to our temp location
shutil.copyfile(gradio_temp_file_path, our_copy_of_pptx_path)
# Now, our_copy_of_pptx_path is the path to the PPTX file within tmpdir.
# convert_pptx_to_pdf will create the PDF also within tmpdir.
pdf_path = convert_pptx_to_pdf(our_copy_of_pptx_path, tmpdir)
# Create persistent copies of the output files for Gradio
import tempfile as tf
# Create persistent PDF file
pdf_fd, persistent_pdf_path = tf.mkstemp(suffix='.pdf', prefix='converted_')
os.close(pdf_fd)
shutil.copy2(pdf_path, persistent_pdf_path)
# Create persistent ZIP file
zip_fd, persistent_zip_path = tf.mkstemp(suffix='.zip', prefix='converted_')
os.close(zip_fd)
zip_path = os.path.join(tmpdir, 'converted.zip')
make_zip_file([pdf_path], zip_path)
shutil.copy2(zip_path, persistent_zip_path)
return persistent_pdf_path, persistent_zip_path
finally:
# Clean up our temporary directory
try:
shutil.rmtree(tmpdir)
except:
pass # Ignore cleanup errors
with gr.Blocks(title="PPTX to PDF Converter - Easily Convert PowerPoint to PDF") as demo:
gr.Markdown("# PPTX to PDF Converter") # Added main title here
# Application Introduction and Instructions - 直接显示,不使用手风琴
gr.Markdown("""
## Application Introduction and Instructions
Welcome to the PPTX to PDF Converter! This tool allows you to easily convert your PowerPoint (PPTX) files into PDF documents.
**Features:**
- **Simple Upload:** Easily upload your PPTX file through the web interface.
- **One-Click Conversion:** Convert your file to PDF with a single click.
- **Direct PDF Download:** Download the converted PDF file directly.
- **Zipped Archive:** Optionally, download a ZIP file containing the converted PDF for convenience.
**How to Use:**
1. **Upload PPTX File:** Click on the "Upload PPTX File" area or drag and drop your `.pptx` file.
2. **Click Convert:** Press the "Convert" button to start the conversion process.
3. **Download Files:** Once the conversion is complete, download links for the PDF file and a ZIP archive (containing the PDF) will appear. Click on your preferred option to download.
""")
gr.Markdown("---")
with gr.Row():
with gr.Column():
pptx_input = gr.File(label="Upload PPTX File", file_types=[".pptx"])
convert_btn = gr.Button("Convert", variant="primary", size="lg")
with gr.Column():
pdf_output = gr.File(label="Download PDF File")
zip_output = gr.File(label="Download ZIP Archive")
# 添加漂亮的下载按钮
with gr.Row():
download_btn = gr.DownloadButton(
label="📦 Download ZIP Package",
variant="secondary",
size="lg",
visible=False
)
def handle_conversion(pptx_file):
if pptx_file is None:
return None, None, gr.update(visible=False)
pdf_path, zip_path = pptx2pdf_web(pptx_file)
# 更新下载按钮,使其可见并设置下载文件
return pdf_path, zip_path, gr.update(visible=True, value=zip_path)
convert_btn.click(
handle_conversion,
inputs=[pptx_input],
outputs=[pdf_output, zip_output, download_btn]
)
demo.queue(default_concurrency_limit=10, max_size=50)
demo.launch(show_api=False)