Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
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():
|