plozia commited on
Commit
0ac70f9
·
verified ·
1 Parent(s): 69b19ba

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -0
app.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
+ from typing import List
4
+ import gradio as gr
5
+ from PyPDF2 import PdfReader, PdfWriter
6
+
7
+ MAX_SIZE_BYTES = 500 * 1024 * 1024 # 500 MB
8
+
9
+ def parse_page_ranges(ranges: str, num_pages: int) -> List[int]:
10
+ """
11
+ Convert a string like "1-3,5,8-10" into a sorted list of zero-based page indices.
12
+ """
13
+ pages = set()
14
+ for part in ranges.split(','):
15
+ part = part.strip()
16
+ if '-' in part:
17
+ start_str, end_str = part.split('-', 1)
18
+ start = max(1, int(start_str))
19
+ end = min(num_pages, int(end_str))
20
+ pages.update(range(start - 1, end))
21
+ else:
22
+ p = int(part)
23
+ if 1 <= p <= num_pages:
24
+ pages.add(p - 1)
25
+ return sorted(pages)
26
+
27
+
28
+ def split_pdf(file, page_ranges: str):
29
+ # Validate file size
30
+ file_size = os.path.getsize(file.name)
31
+ if file_size > MAX_SIZE_BYTES:
32
+ return None, f"File size exceeds 500 MB limit ({file_size / (1024*1024):.2f} MB)."
33
+
34
+ reader = PdfReader(file.name)
35
+ num_pages = len(reader.pages)
36
+ try:
37
+ page_indices = parse_page_ranges(page_ranges, num_pages)
38
+ except Exception as e:
39
+ return None, f"Error parsing page ranges: {e}"
40
+
41
+ if not page_indices:
42
+ return None, "No valid pages selected."
43
+
44
+ writer = PdfWriter()
45
+ for idx in page_indices:
46
+ writer.add_page(reader.pages[idx])
47
+
48
+ out_path = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name
49
+ with open(out_path, "wb") as f_out:
50
+ writer.write(f_out)
51
+
52
+ return out_path, None
53
+
54
+ # Build Gradio interface
55
+ with gr.Blocks(css="""
56
+ #header {text-align: center; margin-bottom: 20px;}
57
+ .input-row {display: flex; gap: 10px; margin-bottom: 20px;}
58
+ .button-row {text-align: center; margin-top: 20px;}
59
+ """) as demo:
60
+ # Header
61
+ gr.HTML("<h1 id='header'>📄 PDF Splitter</h1>")
62
+ gr.Markdown("Upload a PDF (up to 500 MB) and extract specific pages using ranges like `1-3,5,7-9`.")
63
+
64
+ with gr.Row(elem_classes="input-row"):
65
+ pdf_input = gr.File(label="Select PDF file", file_types=['.pdf'])
66
+ page_input = gr.Textbox(label="Page ranges", placeholder="e.g. 1-3,5,7-9")
67
+
68
+ with gr.Row(elem_classes="button-row"):
69
+ split_button = gr.Button("Split PDF", variant="primary")
70
+
71
+ output_file = gr.File(label="Download Split PDF")
72
+ error_text = gr.Textbox(label="Error Message", interactive=False, visible=False)
73
+
74
+ def run_split(file, ranges):
75
+ if file is None or not ranges:
76
+ return None, "Please upload a PDF and specify page ranges.", True
77
+ out_path, error = split_pdf(file, ranges)
78
+ if error:
79
+ return None, error, True
80
+ return out_path, "", False
81
+
82
+ split_button.click(fn=run_split,
83
+ inputs=[pdf_input, page_input],
84
+ outputs=[output_file, error_text, error_text],
85
+ api_name="split_pdf")
86
+
87
+ # Hide error box when no error
88
+ error_text.change(lambda msg: msg != "", inputs=error_text, outputs=error_text)
89
+
90
+ if __name__ == "__main__":
91
+ demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))