125 lines
4.5 KiB
Python
125 lines
4.5 KiB
Python
# app.py (파일 업로드 지원 버전)
|
|
import streamlit as st
|
|
import json
|
|
from pathlib import Path
|
|
import base64
|
|
|
|
# --- 헬퍼 함수 ---
|
|
|
|
def match_uploaded_files(doc_files, json_files):
|
|
"""
|
|
업로드된 두 파일 목록을 받아, 이름(확장자 제외)을 기준으로 매칭하고
|
|
결과를 딕셔너리로 반환합니다.
|
|
"""
|
|
matched_pairs = {}
|
|
|
|
# 각 파일 목록을 이름(stem)을 키로 하는 딕셔너리로 변환
|
|
docs_map = {Path(f.name).stem: f for f in doc_files}
|
|
jsons_map = {Path(f.name).stem: f for f in json_files}
|
|
|
|
# 문서 파일 기준으로 JSON 파일 찾기
|
|
for stem, doc_file in docs_map.items():
|
|
if stem in jsons_map:
|
|
matched_pairs[stem] = {
|
|
"doc_file": doc_file,
|
|
"json_file": jsons_map[stem]
|
|
}
|
|
|
|
return matched_pairs
|
|
|
|
def display_pdf(file_object):
|
|
"""
|
|
업로드된 파일 객체(UploadedFile)를 읽어 PDF를 표시합니다.
|
|
"""
|
|
try:
|
|
# 파일 포인터를 처음으로 되돌림 (중요)
|
|
file_object.seek(0)
|
|
base64_pdf = base64.b64encode(file_object.read()).decode('utf-8')
|
|
pdf_display = f'<iframe src="data:application/pdf;base64,{base64_pdf}" width="100%" height="800" type="application/pdf"></iframe>'
|
|
st.markdown(pdf_display, unsafe_allow_html=True)
|
|
except Exception as e:
|
|
st.error(f"PDF 파일을 표시하는 중 오류가 발생했습니다: {e}")
|
|
|
|
# --- 메인 UI 로직 ---
|
|
|
|
def main():
|
|
st.set_page_config(layout="wide", page_title="결과 비교 도구")
|
|
st.title("📑 파일 업로드 기반 결과 비교 도구")
|
|
st.markdown("---")
|
|
|
|
# --- 1. 파일 업로드 ---
|
|
st.sidebar.header("파일 업로드")
|
|
|
|
uploaded_docs = st.sidebar.file_uploader(
|
|
"1. 원본 문서 파일(들)을 업로드하세요.",
|
|
accept_multiple_files=True,
|
|
type=['png', 'jpg', 'jpeg', 'pdf']
|
|
)
|
|
|
|
uploaded_jsons = st.sidebar.file_uploader(
|
|
"2. 결과 JSON 파일(들)을 업로드하세요.",
|
|
accept_multiple_files=True,
|
|
type=['json']
|
|
)
|
|
|
|
if not uploaded_docs or not uploaded_jsons:
|
|
st.info("사이드바에서 원본 문서와 결과 JSON 파일을 모두 업로드해주세요.")
|
|
return
|
|
|
|
try:
|
|
matched_files = match_uploaded_files(uploaded_docs, uploaded_jsons)
|
|
except Exception as e:
|
|
st.error(f"업로드된 파일을 매칭하는 중 오류가 발생했습니다: {e}")
|
|
return
|
|
|
|
if not matched_files:
|
|
st.warning("업로드된 파일 중 일치하는 문서-JSON 쌍을 찾을 수 없습니다. 파일 이름(확장자 제외)이 동일한지 확인하세요.")
|
|
return
|
|
|
|
# --- 2. 파일 선택 ---
|
|
st.sidebar.header("파일 선택")
|
|
sorted_basenames = sorted(list(matched_files.keys()))
|
|
|
|
selected_basename = st.sidebar.selectbox(
|
|
"비교할 파일을 선택하세요.",
|
|
sorted_basenames
|
|
)
|
|
|
|
if selected_basename:
|
|
st.header(f"🔎 비교 결과: `{selected_basename}`")
|
|
|
|
selected_pair = matched_files[selected_basename]
|
|
doc_file = selected_pair["doc_file"]
|
|
json_file = selected_pair["json_file"]
|
|
|
|
# --- 결과 표시 ---
|
|
col1, col2 = st.columns(2)
|
|
with col1:
|
|
st.subheader(f"원본 문서: `{doc_file.name}`")
|
|
doc_suffix = Path(doc_file.name).suffix.lower()
|
|
|
|
if doc_suffix == ".pdf":
|
|
display_pdf(doc_file)
|
|
elif doc_suffix in ['.png', '.jpg', '.jpeg']:
|
|
st.image(doc_file, caption=f"원본 이미지: {doc_file.name}", use_container_width=True)
|
|
else:
|
|
st.warning("지원하지 않는 문서 형식입니다.")
|
|
|
|
with col2:
|
|
st.subheader(f"추출된 데이터: `{json_file.name}`")
|
|
try:
|
|
# 파일 포인터를 처음으로 되돌림
|
|
json_file.seek(0)
|
|
data = json.load(json_file)
|
|
|
|
result_to_display = data[0] if isinstance(data, list) and data else data
|
|
|
|
if isinstance(result_to_display, dict) and 'fields' in result_to_display:
|
|
del result_to_display['fields']
|
|
|
|
st.json(result_to_display)
|
|
except Exception as e:
|
|
st.error(f"JSON 파일을 읽거나 처리하는 중 오류가 발생했습니다: {e}")
|
|
|
|
if __name__ == "__main__":
|
|
main() |