Update app.py
Browse files
app.py
CHANGED
|
@@ -98,14 +98,14 @@ def extract_text_with_olefile(input_path):
|
|
| 98 |
|
| 99 |
def convert_to_html_subprocess(input_path, output_dir):
|
| 100 |
"""subprocess로 hwp5html 실행"""
|
| 101 |
-
|
|
|
|
| 102 |
|
| 103 |
# 가능한 hwp5html 경로들
|
| 104 |
hwp5html_paths = [
|
| 105 |
'hwp5html', # PATH에 있는 경우
|
| 106 |
os.path.join(SCRIPT_DIR, 'bin', 'hwp5html'),
|
| 107 |
os.path.join(PYHWP_PATH, 'bin', 'hwp5html'),
|
| 108 |
-
sys.executable.replace('python', 'hwp5html'),
|
| 109 |
]
|
| 110 |
|
| 111 |
for cmd_path in hwp5html_paths:
|
|
@@ -119,9 +119,11 @@ def convert_to_html_subprocess(input_path, output_dir):
|
|
| 119 |
|
| 120 |
if result.returncode == 0 and os.path.exists(output_path):
|
| 121 |
return output_path, None
|
|
|
|
| 122 |
except (FileNotFoundError, subprocess.TimeoutExpired):
|
| 123 |
continue
|
| 124 |
except Exception as e:
|
|
|
|
| 125 |
continue
|
| 126 |
|
| 127 |
return None, "hwp5html 명령을 찾을 수 없습니다."
|
|
@@ -228,7 +230,7 @@ def convert_hwp(file, output_format, progress=gr.Progress()):
|
|
| 228 |
# 변환 수행
|
| 229 |
if output_format == "HTML":
|
| 230 |
output_path, error = convert_to_html_subprocess(input_path, tmp_dir)
|
| 231 |
-
ext = ".html"
|
| 232 |
|
| 233 |
elif output_format == "ODT (OpenDocument)":
|
| 234 |
output_path, error = convert_to_odt_subprocess(input_path, tmp_dir)
|
|
@@ -253,10 +255,21 @@ def convert_hwp(file, output_format, progress=gr.Progress()):
|
|
| 253 |
return None, f"❌ 지원하지 않는 형식: {output_format}", ""
|
| 254 |
|
| 255 |
# 변환 실패 처리
|
| 256 |
-
if output_path is None
|
| 257 |
error_msg = error or "변환에 실패했습니다."
|
| 258 |
return None, f"❌ {error_msg}", ""
|
| 259 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
progress(0.8, desc="파일 준비 중...")
|
| 261 |
|
| 262 |
# 최종 파일명 설정
|
|
@@ -264,8 +277,13 @@ def convert_hwp(file, output_format, progress=gr.Progress()):
|
|
| 264 |
final_filename = f"{base_name}{ext}"
|
| 265 |
final_output = os.path.join(tmp_dir, final_filename)
|
| 266 |
|
| 267 |
-
|
| 268 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
|
| 270 |
# 파일 크기 확인
|
| 271 |
file_size = os.path.getsize(final_output)
|
|
@@ -275,7 +293,9 @@ def convert_hwp(file, output_format, progress=gr.Progress()):
|
|
| 275 |
|
| 276 |
# 미리보기 (텍스트/HTML인 경우)
|
| 277 |
preview = ""
|
| 278 |
-
|
|
|
|
|
|
|
| 279 |
try:
|
| 280 |
with open(final_output, 'r', encoding='utf-8', errors='ignore') as f:
|
| 281 |
preview = f.read(5000) # 처음 5000자만
|
|
@@ -283,6 +303,8 @@ def convert_hwp(file, output_format, progress=gr.Progress()):
|
|
| 283 |
preview += "\n\n... (미리보기 생략)"
|
| 284 |
except:
|
| 285 |
pass
|
|
|
|
|
|
|
| 286 |
|
| 287 |
return final_output, f"✅ 변환 완료: {final_filename} ({size_str})", preview
|
| 288 |
|
|
@@ -323,7 +345,9 @@ css = """
|
|
| 323 |
"""
|
| 324 |
|
| 325 |
# Gradio 인터페이스
|
| 326 |
-
with gr.Blocks(
|
|
|
|
|
|
|
| 327 |
with gr.Column(elem_id="col-container"):
|
| 328 |
gr.Markdown("""
|
| 329 |
# 📄 HWP 파일 변환기
|
|
|
|
| 98 |
|
| 99 |
def convert_to_html_subprocess(input_path, output_dir):
|
| 100 |
"""subprocess로 hwp5html 실행"""
|
| 101 |
+
output_name = "output.html"
|
| 102 |
+
output_path = os.path.join(output_dir, output_name)
|
| 103 |
|
| 104 |
# 가능한 hwp5html 경로들
|
| 105 |
hwp5html_paths = [
|
| 106 |
'hwp5html', # PATH에 있는 경우
|
| 107 |
os.path.join(SCRIPT_DIR, 'bin', 'hwp5html'),
|
| 108 |
os.path.join(PYHWP_PATH, 'bin', 'hwp5html'),
|
|
|
|
| 109 |
]
|
| 110 |
|
| 111 |
for cmd_path in hwp5html_paths:
|
|
|
|
| 119 |
|
| 120 |
if result.returncode == 0 and os.path.exists(output_path):
|
| 121 |
return output_path, None
|
| 122 |
+
|
| 123 |
except (FileNotFoundError, subprocess.TimeoutExpired):
|
| 124 |
continue
|
| 125 |
except Exception as e:
|
| 126 |
+
print(f"hwp5html error: {e}")
|
| 127 |
continue
|
| 128 |
|
| 129 |
return None, "hwp5html 명령을 찾을 수 없습니다."
|
|
|
|
| 230 |
# 변환 수행
|
| 231 |
if output_format == "HTML":
|
| 232 |
output_path, error = convert_to_html_subprocess(input_path, tmp_dir)
|
| 233 |
+
ext = ".html" # 디렉토리인 경우 아래에서 .zip으로 변경됨
|
| 234 |
|
| 235 |
elif output_format == "ODT (OpenDocument)":
|
| 236 |
output_path, error = convert_to_odt_subprocess(input_path, tmp_dir)
|
|
|
|
| 255 |
return None, f"❌ 지원하지 않는 형식: {output_format}", ""
|
| 256 |
|
| 257 |
# 변환 실패 처리
|
| 258 |
+
if output_path is None:
|
| 259 |
error_msg = error or "변환에 실패했습니다."
|
| 260 |
return None, f"❌ {error_msg}", ""
|
| 261 |
|
| 262 |
+
# output_path가 디렉토리인지 파일인지 확인
|
| 263 |
+
if os.path.isdir(output_path):
|
| 264 |
+
# 디렉토리인 경우 (HTML 변환 시 발생 가능) - ZIP 압축
|
| 265 |
+
zip_base = os.path.join(tmp_dir, "output_archive")
|
| 266 |
+
zip_path = shutil.make_archive(zip_base, 'zip', output_path)
|
| 267 |
+
output_path = zip_path
|
| 268 |
+
ext = ".zip"
|
| 269 |
+
|
| 270 |
+
if not os.path.exists(output_path):
|
| 271 |
+
return None, "❌ 변환된 파일을 찾을 수 없습니다.", ""
|
| 272 |
+
|
| 273 |
progress(0.8, desc="파일 준비 중...")
|
| 274 |
|
| 275 |
# 최종 파일명 설정
|
|
|
|
| 277 |
final_filename = f"{base_name}{ext}"
|
| 278 |
final_output = os.path.join(tmp_dir, final_filename)
|
| 279 |
|
| 280 |
+
# 파일 이동 (다른 경로일 때만)
|
| 281 |
+
if output_path != final_output and os.path.isfile(output_path):
|
| 282 |
+
shutil.copy2(output_path, final_output)
|
| 283 |
+
elif output_path == final_output:
|
| 284 |
+
pass # 이미 같은 경로
|
| 285 |
+
else:
|
| 286 |
+
final_output = output_path # 이동 실패 시 원본 사용
|
| 287 |
|
| 288 |
# 파일 크기 확인
|
| 289 |
file_size = os.path.getsize(final_output)
|
|
|
|
| 293 |
|
| 294 |
# 미리보기 (텍스트/HTML인 경우)
|
| 295 |
preview = ""
|
| 296 |
+
|
| 297 |
+
# TXT 파일만 미리보기 (HTML은 ZIP이거나 디렉토리일 수 있음)
|
| 298 |
+
if ext == '.txt' and os.path.isfile(final_output):
|
| 299 |
try:
|
| 300 |
with open(final_output, 'r', encoding='utf-8', errors='ignore') as f:
|
| 301 |
preview = f.read(5000) # 처음 5000자만
|
|
|
|
| 303 |
preview += "\n\n... (미리보기 생략)"
|
| 304 |
except:
|
| 305 |
pass
|
| 306 |
+
elif ext == '.zip':
|
| 307 |
+
preview = "📦 HTML 변환 결과가 ZIP 파일로 압축되었습니다.\n다운로드 후 압축을 풀어서 HTML 파일을 확인하세요."
|
| 308 |
|
| 309 |
return final_output, f"✅ 변환 완료: {final_filename} ({size_str})", preview
|
| 310 |
|
|
|
|
| 345 |
"""
|
| 346 |
|
| 347 |
# Gradio 인터페이스
|
| 348 |
+
with gr.Blocks(title="HWP 변환기") as demo:
|
| 349 |
+
# CSS 적용
|
| 350 |
+
gr.HTML(f"<style>{css}</style>")
|
| 351 |
with gr.Column(elem_id="col-container"):
|
| 352 |
gr.Markdown("""
|
| 353 |
# 📄 HWP 파일 변환기
|