data-learner commited on
Commit
ba43ff8
·
verified ·
1 Parent(s): aa74694

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +127 -0
app.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 药店拜访助手 - Hugging Face Spaces 版本
3
+ 使用 Gradio SDK(免费)+ FastAPI 自定义路由
4
+ """
5
+ import gradio as gr
6
+ from fastapi import Request, UploadFile, File
7
+ from fastapi.responses import HTMLResponse, JSONResponse, Response
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+ import io
10
+ import json
11
+ import os
12
+ import sys
13
+ import platform
14
+ import shutil
15
+
16
+ # 确保能导入同目录模块
17
+ WORK_DIR = os.path.dirname(os.path.abspath(__file__))
18
+ sys.path.insert(0, WORK_DIR)
19
+
20
+ # 导入导出服务核心函数
21
+ from export_server import generate_docx
22
+
23
+ # 导入OCR
24
+ import pytesseract
25
+ from PIL import Image
26
+
27
+ # 跨平台 Tesseract 配置
28
+ if platform.system() == 'Windows':
29
+ pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
30
+ os.environ['TESSDATA_PREFIX'] = os.path.expandvars(r'%USERPROFILE%\.tesseract\tessdata')
31
+ else:
32
+ tesseract_bin = shutil.which('tesseract')
33
+ if tesseract_bin:
34
+ pytesseract.pytesseract.tesseract_cmd = tesseract_bin
35
+ for _tessdata in ['/usr/share/tesseract-ocr/5/tessdata',
36
+ '/usr/share/tesseract-ocr/4.00/tessdata',
37
+ '/usr/share/tessdata']:
38
+ if os.path.isdir(_tessdata):
39
+ os.environ.setdefault('TESSDATA_PREFIX', _tessdata)
40
+ break
41
+
42
+ # 读取H5页面内容
43
+ H5_FILE = os.path.join(WORK_DIR, 'test-h5.html')
44
+ with open(H5_FILE, 'r', encoding='utf-8') as f:
45
+ h5_content = f.read()
46
+
47
+ # 创建 Gradio Blocks(HF Spaces 要求 demo 变量)
48
+ demo = gr.Blocks(css="footer{display:none !important}")
49
+
50
+ with demo:
51
+ gr.HTML('<script>window.location.href="/app";</script>')
52
+
53
+ # 启动 Gradio 获取底层 FastAPI 应用
54
+ app, _, _ = demo.launch(
55
+ prevent_thread_lock=True,
56
+ server_name="0.0.0.0",
57
+ server_port=7860,
58
+ quiet=True,
59
+ show_error=True
60
+ )
61
+
62
+ # 添加 CORS 支持
63
+ app.add_middleware(
64
+ CORSMiddleware,
65
+ allow_origins=["*"],
66
+ allow_methods=["*"],
67
+ allow_headers=["*"],
68
+ )
69
+
70
+ # ===== 自定义路由 =====
71
+
72
+ @app.get("/app", response_class=HTMLResponse)
73
+ async def serve_h5():
74
+ """返回 H5 页面"""
75
+ return HTMLResponse(content=h5_content)
76
+
77
+ @app.get("/health")
78
+ async def health():
79
+ """健康检查"""
80
+ return {"status": "ok"}
81
+
82
+ @app.post("/ocr")
83
+ async def ocr_endpoint(file: UploadFile = File(...)):
84
+ """OCR 识别接口"""
85
+ try:
86
+ image_data = await file.read()
87
+ img = Image.open(io.BytesIO(image_data))
88
+ w, h = img.size
89
+ max_dim = 2000
90
+ if w > max_dim or h > max_dim:
91
+ ratio = min(max_dim / w, max_dim / h)
92
+ img = img.resize((int(w * ratio), int(h * ratio)), Image.LANCZOS)
93
+ text = pytesseract.image_to_string(img, lang='chi_sim', config='--psm 6')
94
+ result = {"text": text.strip(), "length": len(text.strip())}
95
+ print(f"[OCR] 识别成功,提取 {len(text.strip())} 个字符")
96
+ return JSONResponse(content=result)
97
+ except Exception as e:
98
+ print(f"[OCR] 识别失败: {e}")
99
+ return JSONResponse(content={"error": f"OCR识别失败: {str(e)}"}, status_code=500)
100
+
101
+ @app.post("/export")
102
+ async def export_endpoint(request: Request):
103
+ """Word 文档导出接口"""
104
+ try:
105
+ body = await request.body()
106
+ visit_data = json.loads(body)
107
+ buffer = generate_docx(visit_data)
108
+ filename = 'visit_%s_%sstores.docx' % (
109
+ visit_data.get('visitDateDisplay', '').replace('.', '-'),
110
+ visit_data.get('totalCount', 0)
111
+ )
112
+ print(f"[Export] 导出成功: {filename}")
113
+ return Response(
114
+ content=buffer.getvalue(),
115
+ media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
116
+ headers={"Content-Disposition": f'attachment; filename="{filename}"'}
117
+ )
118
+ except Exception as e:
119
+ print(f"[Export] 导出失败: {e}")
120
+ return JSONResponse(content={"error": str(e)}, status_code=500)
121
+
122
+ print("=" * 50)
123
+ print(" 药店拜访助手 - HF Spaces 版本已启动")
124
+ print(" H5 页面: /app")
125
+ print(" OCR 接口: /ocr")
126
+ print(" 导出接口: /export")
127
+ print("=" * 50)