innoai commited on
Commit
fb3f182
·
verified ·
1 Parent(s): 5c0ac51

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -79
app.py CHANGED
@@ -1,119 +1,122 @@
 
 
 
 
 
 
 
 
 
 
1
  import os
2
- import subprocess
3
- import gradio as gr
4
  import shutil
 
 
 
5
  from pathlib import Path
6
 
7
- # 程序根目录
8
- BASE_DIR = os.path.dirname(__file__)
9
- # 可执行文件路径:app.py PptxToJpgZip 同目录
10
- BINARY_PATH = os.path.join(BASE_DIR, "PptxToJpgZip")
 
11
 
12
- # 启动时确保二进制有执行权限(在 Hugging Face Spaces 里无法手动 chmod)
13
  try:
14
  os.chmod(BINARY_PATH, 0o755)
15
  except Exception as e:
16
- # 如果权限设置失败,也无需中断,只要后续能调用即可
17
- print(f"⚠️ 警告:设置执行权限失败:{e}")
18
-
19
 
20
- def install_fonts_from_repository():
 
21
  """
22
- 将仓库中的 fonts 目录下的所有字体文件复制到 ~/.fonts 目录,并刷新字体缓存。
 
23
  """
24
  try:
25
- # 获取当前用户的主目录路径
26
- home_dir = Path.home()
27
-
28
- # 定义目标字体目录路径:~/.fonts
29
- fonts_dir = home_dir / ".fonts"
30
-
31
- # 如果 ~/.fonts 目录不存在,则创建该目录
32
- if not fonts_dir.exists():
33
- fonts_dir.mkdir(parents=True)
34
- print(f"已创建字体目录:{fonts_dir}")
35
- else:
36
- print(f"字体目录已存在:{fonts_dir}")
37
 
38
- # 定义仓库中的 fonts 目录路径
39
- repo_fonts_dir = Path(__file__).parent / "fonts"
40
-
41
- # 检查仓库中的 fonts 目录是否存在
42
  if not repo_fonts_dir.exists():
43
- print(f"错误:仓库中的 fonts 目录不存在:{repo_fonts_dir}")
44
  return
45
 
46
- # 支持的字体文件扩展名
47
- font_extensions = [".ttf", ".otf", ".ttc"]
48
-
49
- # 统计已复制的字体文件数量
50
- copied_count = 0
51
-
52
- # 遍历 fonts 目录中的所有文件
53
  for font_file in repo_fonts_dir.iterdir():
54
- if font_file.suffix.lower() in font_extensions:
55
- destination = fonts_dir / font_file.name
56
- try:
57
- shutil.copy(font_file, destination)
58
- print(f"已复制字体文件:{font_file.name} {destination}")
59
- copied_count += 1
60
- except Exception as e:
61
- print(f"复制字体文件时出错:{font_file.name},错误信息:{e}")
62
-
63
- if copied_count == 0:
64
- print("未找到任何可复制的字体文件。")
65
- return
66
-
67
- # 刷新字体缓存(仅在 Linux/Mac 下)
68
- if not sys.platform.startswith('win'):
69
- try:
70
- print("正在刷新字体缓存...")
71
  subprocess.run(["fc-cache", "-f", "-v"], check=True)
72
- print("字体缓存刷新完成。")
73
- except subprocess.CalledProcessError as e:
74
- print(f"刷新字体缓存时出错:{e}")
75
  except Exception as e:
76
- print(f"安装字体时出错:{e}")
77
-
78
 
79
- # 启动时安装字体
80
  install_fonts_from_repository()
81
 
 
 
 
 
82
 
83
- def convert_pptx_to_zip(pptx_file):
84
  """
85
- 调用外部 PptxToJpgZip,可执行文件将上传的 PPTX 转为 JPG 并打包 ZIP。
86
- pptx_file.name Gradio 上传后的临时文件路径。
 
 
87
  """
88
- src_path = pptx_file.name # Gradio 会在后台保存上传文件,并提供 .name 属性
 
 
 
89
 
90
- # 调用外部程序:PptxToJpgZip <输入文件.pptx>
91
  proc = subprocess.run(
92
- [BINARY_PATH, src_path],
 
93
  stdout=subprocess.PIPE,
94
- stderr=subprocess.PIPE
95
  )
 
96
  if proc.returncode != 0:
97
- stderr = proc.stderr.decode("utf-8", errors="ignore")
98
- raise RuntimeError(f"转换失败:\n{stderr}")
 
 
99
 
100
- # 可执行程序会在同目录生成 <原文件名>_images.zip
101
- zip_path = os.path.splitext(src_path)[0] + "_images.zip"
102
- if not os.path.isfile(zip_path):
103
- raise FileNotFoundError(f"转换完成,但未找到输出 ZIP:{zip_path}")
 
 
104
 
105
- return zip_path # Gradio 会自动为此路径生成下载链接
106
 
107
- # —— 构建 Gradio 界面 ——
108
  with gr.Blocks(title="PPTX→JPG→ZIP 转换器") as demo:
109
- gr.Markdown("""
 
110
  # PPTX→JPG→ZIP
111
- 上传一个 `.pptx` 文件,后台调用 `PptxToJpgZip` 可执行程序,
112
- 将每页幻灯片导出为高质量 JPG,并打包成 ZIP,最后提供下载。
113
- """)
114
  with gr.Row():
115
  pptx_in = gr.File(label="上传 PPTX (.pptx)", file_types=[".pptx"])
116
  btn = gr.Button("开始转换")
 
117
  zip_out = gr.File(label="下载 ZIP 文件")
118
 
119
  btn.click(fn=convert_pptx_to_zip, inputs=pptx_in, outputs=zip_out)
@@ -122,5 +125,6 @@ if __name__ == "__main__":
122
  demo.launch(
123
  server_name="0.0.0.0",
124
  server_port=7860,
125
- share=False
 
126
  )
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ PPTX → JPG → ZIP 在线转换(Hugging Face Spaces / 任意 Linux 环境)
5
+ ---------------------------------------------------------------
6
+ - 上传 .pptx → 调用 PptxToJpgZip → 返回 _images.zip
7
+ - 兼容含中文文件名、空格路径
8
+ - 启动时自动安装仓库内字体
9
+ """
10
+
11
  import os
12
+ import sys # 解决 “name 'sys' is not defined”
 
13
  import shutil
14
+ import subprocess
15
+ import tempfile
16
+ import uuid
17
  from pathlib import Path
18
 
19
+ import gradio as gr
20
+
21
+ # ============ 基础路径 ============ #
22
+ BASE_DIR = Path(__file__).parent.resolve()
23
+ BINARY_PATH = BASE_DIR / "PptxToJpgZip" # 可执行文件与 app.py 同目录
24
 
25
+ # ============ 确保可执行权限 ============ #
26
  try:
27
  os.chmod(BINARY_PATH, 0o755)
28
  except Exception as e:
29
+ print(f"⚠️ 无法修改 {BINARY_PATH} 执行权限:{e}")
 
 
30
 
31
+ # ============ 安装字体 ============ #
32
+ def install_fonts_from_repository() -> None:
33
  """
34
+ repo/fonts 内的字体复制到 ~/.fonts,并刷新字体缓存
35
+ (HF Spaces 容器默认存在 fontconfig)
36
  """
37
  try:
38
+ home_fonts_dir = Path.home() / ".fonts"
39
+ home_fonts_dir.mkdir(parents=True, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
40
 
41
+ repo_fonts_dir = BASE_DIR / "fonts"
 
 
 
42
  if not repo_fonts_dir.exists():
43
+ print(f" 未找到字体目录:{repo_fonts_dir}")
44
  return
45
 
46
+ exts = {".ttf", ".otf", ".ttc"}
47
+ copied = 0
 
 
 
 
 
48
  for font_file in repo_fonts_dir.iterdir():
49
+ if font_file.suffix.lower() in exts:
50
+ dest = home_fonts_dir / font_file.name
51
+ shutil.copy(font_file, dest)
52
+ print(f"✅ 已复制字体:{font_file.name}")
53
+ copied += 1
54
+
55
+ if copied:
56
+ # 刷新缓存(Linux / Mac)
57
+ if not sys.platform.startswith("win"):
58
+ print("🔄 刷新字体缓存 …")
 
 
 
 
 
 
 
59
  subprocess.run(["fc-cache", "-f", "-v"], check=True)
60
+ print("✅ 字体缓存刷新完成")
61
+ else:
62
+ print("⚠️ 未找到可复制的字体文件")
63
  except Exception as e:
64
+ print(f"⚠️ 安装字体失败:{e}")
 
65
 
 
66
  install_fonts_from_repository()
67
 
68
+ # ============ PPTX → ZIP 主逻辑 ============ #
69
+ def _generate_safe_name() -> str:
70
+ """生成仅含 ASCII 的随机文件名(避免中文路径问题)"""
71
+ return f"input_{uuid.uuid4().hex}.pptx"
72
 
73
+ def convert_pptx_to_zip(pptx_file) -> str:
74
  """
75
+ 1. 创建临时工作目录 tmpdir
76
+ 2. 将上传的 PPTX 复制为 ASCII 文件名
77
+ 3. 在 tmpdir 中调用 PptxToJpgZip
78
+ 4. 搜索 *_images.zip 并返回其路径
79
  """
80
+ # -------- 准备工作目录 -------- #
81
+ tmpdir = Path(tempfile.mkdtemp())
82
+ safe_pptx = tmpdir / _generate_safe_name()
83
+ shutil.copy(pptx_file.name, safe_pptx)
84
 
85
+ # -------- 调用外部程序 -------- #
86
  proc = subprocess.run(
87
+ [str(BINARY_PATH), str(safe_pptx)],
88
+ cwd=tmpdir, # 关键:工作目录设为 tmpdir
89
  stdout=subprocess.PIPE,
90
+ stderr=subprocess.PIPE,
91
  )
92
+
93
  if proc.returncode != 0:
94
+ raise RuntimeError(
95
+ f"转换失败,PptxToJpgZip 返回码 {proc.returncode}:\n"
96
+ f"{proc.stderr.decode(errors='ignore')}"
97
+ )
98
 
99
+ # -------- 查找输出 ZIP -------- #
100
+ zips = list(tmpdir.glob("*_images.zip"))
101
+ if not zips:
102
+ raise FileNotFoundError("转换成功,但未在临时目录找到 *_images.zip 输出文件")
103
+ if len(zips) > 1:
104
+ raise RuntimeError("检测到多个 *_images.zip,无法确定返回哪一个")
105
 
106
+ return str(zips[0]) # Gradio 会自动生成下载链接
107
 
108
+ # ============ Gradio UI ============ #
109
  with gr.Blocks(title="PPTX→JPG→ZIP 转换器") as demo:
110
+ gr.Markdown(
111
+ """
112
  # PPTX→JPG→ZIP
113
+ 上传一个 `.pptx` 文件,后台调用 **PptxToJpgZip** 可执行程序,
114
+ 将每页幻灯片导出为高质量 JPG,并打包成 ZIP,最后提供下载。"""
115
+ )
116
  with gr.Row():
117
  pptx_in = gr.File(label="上传 PPTX (.pptx)", file_types=[".pptx"])
118
  btn = gr.Button("开始转换")
119
+
120
  zip_out = gr.File(label="下载 ZIP 文件")
121
 
122
  btn.click(fn=convert_pptx_to_zip, inputs=pptx_in, outputs=zip_out)
 
125
  demo.launch(
126
  server_name="0.0.0.0",
127
  server_port=7860,
128
+ share=False,
129
+ # Spaces 如果需要关掉 SSR,可加 ssr_mode=False
130
  )