🔧 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:
@@ -511,7 +511,7 @@ async def get_document_content(
|
|||||||
@router.get("/{document_id}/pdf")
|
@router.get("/{document_id}/pdf")
|
||||||
async def get_document_pdf(
|
async def get_document_pdf(
|
||||||
document_id: str,
|
document_id: str,
|
||||||
token: Optional[str] = Query(None),
|
_token: Optional[str] = Query(None),
|
||||||
current_user: User = Depends(get_current_active_user),
|
current_user: User = Depends(get_current_active_user),
|
||||||
db: AsyncSession = Depends(get_db)
|
db: AsyncSession = Depends(get_db)
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -483,12 +483,21 @@
|
|||||||
<!-- PDF 뷰어 컨테이너 -->
|
<!-- PDF 뷰어 컨테이너 -->
|
||||||
<div class="border rounded-lg overflow-hidden bg-gray-100 relative" style="height: 500px;">
|
<div class="border rounded-lg overflow-hidden bg-gray-100 relative" style="height: 500px;">
|
||||||
<!-- PDF iframe 뷰어 -->
|
<!-- PDF iframe 뷰어 -->
|
||||||
<iframe :src="`/api/documents/${previewResult?.document_id}/pdf`"
|
<iframe x-show="!pdfError && !pdfLoading"
|
||||||
class="w-full h-full border-0"
|
class="w-full h-full border-0"
|
||||||
x-show="!pdfError"
|
:src="pdfSrc"
|
||||||
@error="pdfError = true">
|
@load="pdfLoaded = true"
|
||||||
|
@error="handlePdfError()">
|
||||||
</iframe>
|
</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 x-show="pdfError" class="flex items-center justify-center h-full text-gray-500">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<i class="fas fa-exclamation-triangle text-2xl mb-2"></i>
|
<i class="fas fa-exclamation-triangle text-2xl mb-2"></i>
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ window.searchApp = function() {
|
|||||||
previewResult: null,
|
previewResult: null,
|
||||||
previewLoading: false,
|
previewLoading: false,
|
||||||
pdfError: false,
|
pdfError: false,
|
||||||
|
pdfLoading: false,
|
||||||
|
pdfLoaded: false,
|
||||||
|
pdfSrc: '',
|
||||||
|
|
||||||
// HTML 뷰어 상태
|
// HTML 뷰어 상태
|
||||||
htmlLoading: false,
|
htmlLoading: false,
|
||||||
@@ -215,8 +218,8 @@ window.searchApp = function() {
|
|||||||
|
|
||||||
// PDF가 있으면 PDF 미리보기, 없으면 HTML 미리보기
|
// PDF가 있으면 PDF 미리보기, 없으면 HTML 미리보기
|
||||||
if (docInfo.pdf_path) {
|
if (docInfo.pdf_path) {
|
||||||
// PDF 미리보기는 iframe으로 자동 처리
|
// PDF 미리보기 준비
|
||||||
console.log('PDF 미리보기 준비 완료');
|
await this.loadPdfPreview(result.document_id);
|
||||||
} else if (docInfo.html_path) {
|
} else if (docInfo.html_path) {
|
||||||
// HTML 문서 미리보기
|
// HTML 문서 미리보기
|
||||||
await this.loadHtmlPreview(result.document_id);
|
await this.loadHtmlPreview(result.document_id);
|
||||||
@@ -318,12 +321,55 @@ window.searchApp = function() {
|
|||||||
this.previewLoading = false;
|
this.previewLoading = false;
|
||||||
this.pdfError = false;
|
this.pdfError = false;
|
||||||
|
|
||||||
|
// PDF 리소스 정리
|
||||||
|
this.pdfLoading = false;
|
||||||
|
this.pdfLoaded = false;
|
||||||
|
this.pdfSrc = '';
|
||||||
|
|
||||||
// HTML 리소스 정리
|
// HTML 리소스 정리
|
||||||
this.htmlLoading = false;
|
this.htmlLoading = false;
|
||||||
this.htmlRawMode = false;
|
this.htmlRawMode = false;
|
||||||
this.htmlSourceCode = '';
|
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 미리보기 로드
|
// HTML 미리보기 로드
|
||||||
async loadHtmlPreview(documentId) {
|
async loadHtmlPreview(documentId) {
|
||||||
this.htmlLoading = true;
|
this.htmlLoading = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user