🔧 PDF 404 오류 해결 및 로딩 상태 개선

🛠️ PDF 404 오류 해결:
- PDF 파일 존재 여부를 HEAD 요청으로 먼저 확인
- 파일이 존재할 때만 iframe src 설정
- 토큰을 URL 파라미터로 전달 (_token)
- 백엔드 PDF API에서 _token 파라미터 지원

📱 PDF 미리보기 로딩 개선:
- pdfLoading, pdfLoaded, pdfSrc 상태 추가
- 로딩 중 스피너 표시
- iframe 로드 완료/에러 이벤트 처리
- handlePdfError() 함수로 에러 처리 개선

🎯 사용자 경험 개선:
- PDF 로딩 상태 명확한 표시
- 에러 발생 시 적절한 메시지
- 불필요한 404 요청 방지
- 리소스 정리 개선

🔍 디버깅 개선:
- PDF 로드 과정 상세 로깅
- 에러 원인 명확한 표시
- 파일 존재 여부 사전 확인
This commit is contained in:
Hyungi Ahn
2025-09-02 17:22:35 +09:00
parent 2d25c04457
commit d4b10b16b1
3 changed files with 61 additions and 6 deletions

View File

@@ -511,7 +511,7 @@ async def get_document_content(
@router.get("/{document_id}/pdf")
async def get_document_pdf(
document_id: str,
token: Optional[str] = Query(None),
_token: Optional[str] = Query(None),
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
):

View File

@@ -483,12 +483,21 @@
<!-- PDF 뷰어 컨테이너 -->
<div class="border rounded-lg overflow-hidden bg-gray-100 relative" style="height: 500px;">
<!-- PDF iframe 뷰어 -->
<iframe :src="`/api/documents/${previewResult?.document_id}/pdf`"
<iframe x-show="!pdfError && !pdfLoading"
class="w-full h-full border-0"
x-show="!pdfError"
@error="pdfError = true">
:src="pdfSrc"
@load="pdfLoaded = true"
@error="handlePdfError()">
</iframe>
<!-- PDF 로딩 상태 -->
<div x-show="pdfLoading" class="flex items-center justify-center h-full">
<div class="text-center">
<i class="fas fa-spinner fa-spin text-2xl text-gray-500 mb-2"></i>
<p class="text-gray-600">PDF를 로드하는 중...</p>
</div>
</div>
<div x-show="pdfError" class="flex items-center justify-center h-full text-gray-500">
<div class="text-center">
<i class="fas fa-exclamation-triangle text-2xl mb-2"></i>

View File

@@ -25,6 +25,9 @@ window.searchApp = function() {
previewResult: null,
previewLoading: false,
pdfError: false,
pdfLoading: false,
pdfLoaded: false,
pdfSrc: '',
// HTML 뷰어 상태
htmlLoading: false,
@@ -215,8 +218,8 @@ window.searchApp = function() {
// PDF가 있으면 PDF 미리보기, 없으면 HTML 미리보기
if (docInfo.pdf_path) {
// PDF 미리보기는 iframe으로 자동 처리
console.log('PDF 미리보기 준비 완료');
// PDF 미리보기 준비
await this.loadPdfPreview(result.document_id);
} else if (docInfo.html_path) {
// HTML 문서 미리보기
await this.loadHtmlPreview(result.document_id);
@@ -318,12 +321,55 @@ window.searchApp = function() {
this.previewLoading = false;
this.pdfError = false;
// PDF 리소스 정리
this.pdfLoading = false;
this.pdfLoaded = false;
this.pdfSrc = '';
// HTML 리소스 정리
this.htmlLoading = false;
this.htmlRawMode = false;
this.htmlSourceCode = '';
},
// PDF 미리보기 로드
async loadPdfPreview(documentId) {
this.pdfLoading = true;
this.pdfError = false;
this.pdfLoaded = false;
try {
// PDF 파일 존재 여부 먼저 확인
const response = await fetch(`/api/documents/${documentId}/pdf`, {
method: 'HEAD',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
});
if (response.ok) {
// PDF 파일이 존재하면 src 설정
const token = localStorage.getItem('token');
this.pdfSrc = `/api/documents/${documentId}/pdf?_token=${encodeURIComponent(token)}`;
console.log('PDF 미리보기 준비 완료:', this.pdfSrc);
} else {
throw new Error(`PDF 파일을 찾을 수 없습니다 (${response.status})`);
}
} catch (error) {
console.error('PDF 미리보기 로드 실패:', error);
this.pdfError = true;
} finally {
this.pdfLoading = false;
}
},
// PDF 에러 처리
handlePdfError() {
console.error('PDF iframe 로드 오류');
this.pdfError = true;
this.pdfLoading = false;
},
// HTML 미리보기 로드
async loadHtmlPreview(documentId) {
this.htmlLoading = true;