Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -228,6 +228,17 @@ function open(i){
|
|
| 228 |
if(fb){fb.destroy();viewer.innerHTML='';}
|
| 229 |
|
| 230 |
if(pages[0].path) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
// μλ² PDF νμΌ λ‘λ
|
| 232 |
fetch(`/api/pdf-content?path=${encodeURIComponent(pages[0].path)}`)
|
| 233 |
.then(response => {
|
|
@@ -246,25 +257,42 @@ function open(i){
|
|
| 246 |
console.log('PDF λ¬Έμ λ‘λ μλ£. νμ΄μ§ μ:', pdf.numPages);
|
| 247 |
|
| 248 |
const pdfPages = [];
|
|
|
|
|
|
|
| 249 |
for(let p = 1; p <= pdf.numPages; p++) {
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
const vp = pg.getViewport({scale: 1});
|
| 254 |
-
const c = document.createElement('canvas');
|
| 255 |
-
c.width = vp.width;
|
| 256 |
-
c.height = vp.height;
|
| 257 |
|
| 258 |
-
|
| 259 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
}
|
| 261 |
|
| 262 |
console.log('λͺ¨λ νμ΄μ§ λ λλ§ μλ£:', pdfPages.length);
|
| 263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
})
|
| 265 |
.catch(error => {
|
| 266 |
console.error('PDF μ²λ¦¬ μ€ μ€λ₯ λ°μ:', error);
|
| 267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
});
|
| 269 |
} else {
|
| 270 |
// μ
λ‘λλ νλ‘μ νΈ λ³΄κΈ°
|
|
@@ -297,11 +325,38 @@ function createFlipBook(pages) {
|
|
| 297 |
}
|
| 298 |
|
| 299 |
/* ββ λ€λΉκ²μ΄μ
ββ */
|
| 300 |
-
$id('homeBtn').onclick=()=>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
function toggle(showHome){
|
| 302 |
$id('home').style.display=showHome?'block':'none';
|
| 303 |
$id('viewerPage').style.display=showHome?'none':'block';
|
| 304 |
$id('homeBtn').style.display=showHome?'none':'inline-block';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 305 |
}
|
| 306 |
|
| 307 |
// νμ΄μ§ λ‘λ μ μλ² PDF λ‘λ
|
|
@@ -351,20 +406,28 @@ async def get_pdf_content(path: str):
|
|
| 351 |
with open(path, "rb") as pdf_file:
|
| 352 |
content = pdf_file.read()
|
| 353 |
|
| 354 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
headers = {
|
| 356 |
"Content-Type": "application/pdf",
|
| 357 |
-
"Content-Disposition": f"inline; filename
|
| 358 |
}
|
| 359 |
|
| 360 |
-
# νμΌ μ½ν
μΈ λ°ν
|
| 361 |
from fastapi.responses import Response
|
| 362 |
-
return Response(content=content,
|
| 363 |
except Exception as e:
|
| 364 |
import traceback
|
| 365 |
error_details = traceback.format_exc()
|
| 366 |
print(f"PDF μ½ν
μΈ λ‘λ μ€λ₯: {str(e)}\n{error_details}")
|
| 367 |
-
|
|
|
|
|
|
|
|
|
|
| 368 |
|
| 369 |
@app.get("/", response_class=HTMLResponse)
|
| 370 |
async def root():
|
|
|
|
| 228 |
if(fb){fb.destroy();viewer.innerHTML='';}
|
| 229 |
|
| 230 |
if(pages[0].path) {
|
| 231 |
+
// λ‘λ© νμ
|
| 232 |
+
viewer.innerHTML = '<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;"><div style="border:4px solid #f3f3f3;border-top:4px solid #3498db;border-radius:50%;width:50px;height:50px;margin:0 auto;animation:spin 2s linear infinite;"></div><p style="margin-top:20px;font-size:16px;">PDF λ‘λ© μ€...</p></div>';
|
| 233 |
+
|
| 234 |
+
// μ€νμΌ μΆκ°
|
| 235 |
+
if (!document.getElementById('loadingStyle')) {
|
| 236 |
+
const style = document.createElement('style');
|
| 237 |
+
style.id = 'loadingStyle';
|
| 238 |
+
style.textContent = '@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}';
|
| 239 |
+
document.head.appendChild(style);
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
// μλ² PDF νμΌ λ‘λ
|
| 243 |
fetch(`/api/pdf-content?path=${encodeURIComponent(pages[0].path)}`)
|
| 244 |
.then(response => {
|
|
|
|
| 257 |
console.log('PDF λ¬Έμ λ‘λ μλ£. νμ΄μ§ μ:', pdf.numPages);
|
| 258 |
|
| 259 |
const pdfPages = [];
|
| 260 |
+
const progressElement = viewer.querySelector('p');
|
| 261 |
+
|
| 262 |
for(let p = 1; p <= pdf.numPages; p++) {
|
| 263 |
+
if (progressElement) {
|
| 264 |
+
progressElement.textContent = `PDF νμ΄μ§ λ‘λ© μ€... (${p}/${pdf.numPages})`;
|
| 265 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
|
| 267 |
+
try {
|
| 268 |
+
const pg = await pdf.getPage(p);
|
| 269 |
+
const vp = pg.getViewport({scale: 1});
|
| 270 |
+
const c = document.createElement('canvas');
|
| 271 |
+
c.width = vp.width;
|
| 272 |
+
c.height = vp.height;
|
| 273 |
+
|
| 274 |
+
await pg.render({canvasContext: c.getContext('2d'), viewport: vp}).promise;
|
| 275 |
+
pdfPages.push({src: c.toDataURL(), thumb: c.toDataURL()});
|
| 276 |
+
} catch (pageError) {
|
| 277 |
+
console.error(`νμ΄μ§ ${p} λ λλ§ μ€λ₯:`, pageError);
|
| 278 |
+
}
|
| 279 |
}
|
| 280 |
|
| 281 |
console.log('λͺ¨λ νμ΄μ§ λ λλ§ μλ£:', pdfPages.length);
|
| 282 |
+
|
| 283 |
+
if (pdfPages.length > 0) {
|
| 284 |
+
createFlipBook(pdfPages);
|
| 285 |
+
} else {
|
| 286 |
+
throw new Error('PDFμμ νμ΄μ§λ₯Ό μΆμΆν μ μμ΅λλ€.');
|
| 287 |
+
}
|
| 288 |
})
|
| 289 |
.catch(error => {
|
| 290 |
console.error('PDF μ²λ¦¬ μ€ μ€λ₯ λ°μ:', error);
|
| 291 |
+
viewer.innerHTML = `<div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;"><p style="color:red;font-size:16px;">PDFλ₯Ό λ‘λνλ μ€ μ€λ₯κ° λ°μνμ΅λλ€:<br>${error.message}</p><button id="backBtn" style="margin-top:20px;padding:10px 20px;background:#0077c2;color:white;border:none;border-radius:4px;cursor:pointer;">νμΌλ‘ λμκ°κΈ°</button></div>`;
|
| 292 |
+
|
| 293 |
+
document.getElementById('backBtn').addEventListener('click', function() {
|
| 294 |
+
toggle(true);
|
| 295 |
+
});
|
| 296 |
});
|
| 297 |
} else {
|
| 298 |
// μ
λ‘λλ νλ‘μ νΈ λ³΄κΈ°
|
|
|
|
| 325 |
}
|
| 326 |
|
| 327 |
/* ββ λ€λΉκ²μ΄μ
ββ */
|
| 328 |
+
$id('homeBtn').onclick=()=>{
|
| 329 |
+
if(fb) {
|
| 330 |
+
fb.destroy();
|
| 331 |
+
viewer.innerHTML = '';
|
| 332 |
+
fb = null;
|
| 333 |
+
}
|
| 334 |
+
toggle(true);
|
| 335 |
+
};
|
| 336 |
+
|
| 337 |
function toggle(showHome){
|
| 338 |
$id('home').style.display=showHome?'block':'none';
|
| 339 |
$id('viewerPage').style.display=showHome?'none':'block';
|
| 340 |
$id('homeBtn').style.display=showHome?'none':'inline-block';
|
| 341 |
+
|
| 342 |
+
// μΆκ°: μ 체 νλ©΄ λͺ¨λμμ homeBtn μμΉ μ‘°μ
|
| 343 |
+
if(!showHome) {
|
| 344 |
+
$id('homeBtn').style.position = 'fixed';
|
| 345 |
+
$id('homeBtn').style.top = '20px';
|
| 346 |
+
$id('homeBtn').style.left = '20px';
|
| 347 |
+
$id('homeBtn').style.zIndex = '1001'; // λ·°μ΄λ³΄λ€ λμ z-index
|
| 348 |
+
$id('homeBtn').style.fontSize = '24px'; // ν¬κΈ° μ¦κ°
|
| 349 |
+
$id('homeBtn').style.width = '48px';
|
| 350 |
+
$id('homeBtn').style.height = '48px';
|
| 351 |
+
} else {
|
| 352 |
+
$id('homeBtn').style.position = '';
|
| 353 |
+
$id('homeBtn').style.top = '';
|
| 354 |
+
$id('homeBtn').style.left = '';
|
| 355 |
+
$id('homeBtn').style.zIndex = '';
|
| 356 |
+
$id('homeBtn').style.fontSize = '';
|
| 357 |
+
$id('homeBtn').style.width = '';
|
| 358 |
+
$id('homeBtn').style.height = '';
|
| 359 |
+
}
|
| 360 |
}
|
| 361 |
|
| 362 |
// νμ΄μ§ λ‘λ μ μλ² PDF λ‘λ
|
|
|
|
| 406 |
with open(path, "rb") as pdf_file:
|
| 407 |
content = pdf_file.read()
|
| 408 |
|
| 409 |
+
# νμΌλͺ
μ²λ¦¬ - URL μΈμ½λ©μΌλ‘ νκΈ λ± νΉμ λ¬Έμ μ²λ¦¬
|
| 410 |
+
import urllib.parse
|
| 411 |
+
filename = pdf_path.name
|
| 412 |
+
encoded_filename = urllib.parse.quote(filename)
|
| 413 |
+
|
| 414 |
+
# μλ΅ ν€λ μ€μ - RFC 6266 νμ€ μ¬μ©
|
| 415 |
headers = {
|
| 416 |
"Content-Type": "application/pdf",
|
| 417 |
+
"Content-Disposition": f"inline; filename=\"{encoded_filename}\"; filename*=UTF-8''{encoded_filename}"
|
| 418 |
}
|
| 419 |
|
| 420 |
+
# νμΌ μ½ν
μΈ μ§μ λ°ν (dictκ° μλ Response κ°μ²΄)
|
| 421 |
from fastapi.responses import Response
|
| 422 |
+
return Response(content=content, media_type="application/pdf")
|
| 423 |
except Exception as e:
|
| 424 |
import traceback
|
| 425 |
error_details = traceback.format_exc()
|
| 426 |
print(f"PDF μ½ν
μΈ λ‘λ μ€λ₯: {str(e)}\n{error_details}")
|
| 427 |
+
|
| 428 |
+
# μ€λ₯ μλ΅ λ°ν (JSON νμ)
|
| 429 |
+
from fastapi.responses import JSONResponse
|
| 430 |
+
return JSONResponse(content={"error": str(e)}, status_code=500)
|
| 431 |
|
| 432 |
@app.get("/", response_class=HTMLResponse)
|
| 433 |
async def root():
|