bluenevus commited on
Commit
57c7f35
·
verified ·
1 Parent(s): ba2629d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -7
app.py CHANGED
@@ -2,6 +2,7 @@ import base64
2
  import io
3
  import os
4
  import zipfile
 
5
  from threading import Thread
6
 
7
  import dash
@@ -10,6 +11,10 @@ from dash import dcc, html, Input, Output, State, callback, MATCH, ALL
10
  from dash.exceptions import PreventUpdate
11
  from PyPDF2 import PdfReader, PdfWriter
12
 
 
 
 
 
13
  app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
14
 
15
  # Global variables
@@ -50,6 +55,7 @@ app.layout = dbc.Container([
50
  dbc.Progress(id='progress-bar', className="my-3"),
51
  dbc.Button("Download ZIP", id='download-button', color="success", className="mt-3", disabled=True),
52
  dcc.Download(id="download-zip"),
 
53
  ], fluid=True)
54
 
55
  @callback(
@@ -60,6 +66,7 @@ app.layout = dbc.Container([
60
  )
61
  def update_output(contents, filename):
62
  if contents is not None:
 
63
  return f"Selected file: {filename}", False
64
  return "No file selected", True
65
 
@@ -75,6 +82,7 @@ def manage_ranges(add_clicks, remove_clicks, existing_ranges):
75
  triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
76
 
77
  if triggered_id == 'add-range':
 
78
  new_index = len(existing_ranges)
79
  new_range = dbc.Row([
80
  dbc.Col(dbc.Input(id={'type': 'range-input', 'index': new_index}, type='text', placeholder='Enter page range (e.g., 1-3)'), width=10),
@@ -83,6 +91,7 @@ def manage_ranges(add_clicks, remove_clicks, existing_ranges):
83
  existing_ranges.append(new_range)
84
  elif 'remove-range' in triggered_id:
85
  remove_index = json.loads(triggered_id)['index']
 
86
  existing_ranges = [range for range in existing_ranges if json.loads(range['props']['children'][1]['props']['children']['props']['id'])['index'] != remove_index]
87
 
88
  return existing_ranges
@@ -90,15 +99,18 @@ def manage_ranges(add_clicks, remove_clicks, existing_ranges):
90
  def process_pdf(contents, filename, ranges):
91
  global generated_file, progress
92
  progress = 0
 
93
 
94
  try:
95
  content_type, content_string = contents.split(',')
96
  decoded = base64.b64decode(content_string)
97
  pdf = PdfReader(io.BytesIO(decoded))
 
98
 
99
  writers = []
100
  for range_str in ranges:
101
  start, end = map(int, range_str.split('-'))
 
102
  writer = PdfWriter()
103
  for i in range(start - 1, min(end, len(pdf.pages))):
104
  writer.add_page(pdf.pages[i])
@@ -108,6 +120,7 @@ def process_pdf(contents, filename, ranges):
108
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
109
  for i, writer in enumerate(writers):
110
  progress = (i + 1) / len(writers) * 100
 
111
  pdf_buffer = io.BytesIO()
112
  writer.write(pdf_buffer)
113
  pdf_buffer.seek(0)
@@ -116,13 +129,15 @@ def process_pdf(contents, filename, ranges):
116
  zip_buffer.seek(0)
117
  generated_file = zip_buffer.getvalue()
118
  progress = 100
 
119
  except Exception as e:
120
- print(f"Error processing PDF: {str(e)}")
121
  progress = -1
122
 
123
  @callback(
124
  Output('progress-bar', 'value'),
125
  Output('download-button', 'disabled'),
 
126
  Input('split-button', 'n_clicks'),
127
  State('upload-pdf', 'contents'),
128
  State('upload-pdf', 'filename'),
@@ -131,28 +146,35 @@ def process_pdf(contents, filename, ranges):
131
  )
132
  def split_pdf(n_clicks, contents, filename, ranges):
133
  if not contents or not ranges:
 
134
  raise PreventUpdate
135
 
 
136
  ranges = [r for r in ranges if r] # Filter out empty ranges
 
 
137
  thread = Thread(target=process_pdf, args=(contents, filename, ranges))
138
  thread.start()
139
 
140
- return 0, True
141
 
142
  @callback(
143
  Output('progress-bar', 'value', allow_duplicate=True),
144
  Output('download-button', 'disabled', allow_duplicate=True),
 
145
  Input('progress-bar', 'value'),
146
  prevent_initial_call=True
147
  )
148
  def update_progress(value):
149
  global progress
150
  if progress == 100:
151
- return 100, False
 
152
  elif progress == -1:
153
- return 0, True
 
154
  else:
155
- return progress, True
156
 
157
  @callback(
158
  Output("download-zip", "data"),
@@ -162,10 +184,12 @@ def update_progress(value):
162
  def download_zip(n_clicks):
163
  global generated_file
164
  if generated_file is not None:
 
165
  return dcc.send_bytes(generated_file, "split_pdfs.zip")
 
166
  raise PreventUpdate
167
 
168
  if __name__ == '__main__':
169
- print("Starting the Dash application...")
170
  app.run(debug=True, host='0.0.0.0', port=7860)
171
- print("Dash application has finished running.")
 
2
  import io
3
  import os
4
  import zipfile
5
+ import logging
6
  from threading import Thread
7
 
8
  import dash
 
11
  from dash.exceptions import PreventUpdate
12
  from PyPDF2 import PdfReader, PdfWriter
13
 
14
+ # Set up logging
15
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
16
+ logger = logging.getLogger(__name__)
17
+
18
  app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
19
 
20
  # Global variables
 
55
  dbc.Progress(id='progress-bar', className="my-3"),
56
  dbc.Button("Download ZIP", id='download-button', color="success", className="mt-3", disabled=True),
57
  dcc.Download(id="download-zip"),
58
+ html.Div(id='log-output', style={'whiteSpace': 'pre-line'}), # Add this line for log output
59
  ], fluid=True)
60
 
61
  @callback(
 
66
  )
67
  def update_output(contents, filename):
68
  if contents is not None:
69
+ logger.info(f"PDF file uploaded: {filename}")
70
  return f"Selected file: {filename}", False
71
  return "No file selected", True
72
 
 
82
  triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
83
 
84
  if triggered_id == 'add-range':
85
+ logger.info("Adding new range input")
86
  new_index = len(existing_ranges)
87
  new_range = dbc.Row([
88
  dbc.Col(dbc.Input(id={'type': 'range-input', 'index': new_index}, type='text', placeholder='Enter page range (e.g., 1-3)'), width=10),
 
91
  existing_ranges.append(new_range)
92
  elif 'remove-range' in triggered_id:
93
  remove_index = json.loads(triggered_id)['index']
94
+ logger.info(f"Removing range input at index {remove_index}")
95
  existing_ranges = [range for range in existing_ranges if json.loads(range['props']['children'][1]['props']['children']['props']['id'])['index'] != remove_index]
96
 
97
  return existing_ranges
 
99
  def process_pdf(contents, filename, ranges):
100
  global generated_file, progress
101
  progress = 0
102
+ logger.info(f"Starting PDF processing for file: {filename}")
103
 
104
  try:
105
  content_type, content_string = contents.split(',')
106
  decoded = base64.b64decode(content_string)
107
  pdf = PdfReader(io.BytesIO(decoded))
108
+ logger.info(f"PDF loaded successfully. Total pages: {len(pdf.pages)}")
109
 
110
  writers = []
111
  for range_str in ranges:
112
  start, end = map(int, range_str.split('-'))
113
+ logger.info(f"Processing range: {start}-{end}")
114
  writer = PdfWriter()
115
  for i in range(start - 1, min(end, len(pdf.pages))):
116
  writer.add_page(pdf.pages[i])
 
120
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
121
  for i, writer in enumerate(writers):
122
  progress = (i + 1) / len(writers) * 100
123
+ logger.info(f"Creating split PDF {i+1}/{len(writers)}")
124
  pdf_buffer = io.BytesIO()
125
  writer.write(pdf_buffer)
126
  pdf_buffer.seek(0)
 
129
  zip_buffer.seek(0)
130
  generated_file = zip_buffer.getvalue()
131
  progress = 100
132
+ logger.info("PDF processing completed successfully")
133
  except Exception as e:
134
+ logger.error(f"Error processing PDF: {str(e)}", exc_info=True)
135
  progress = -1
136
 
137
  @callback(
138
  Output('progress-bar', 'value'),
139
  Output('download-button', 'disabled'),
140
+ Output('log-output', 'children'),
141
  Input('split-button', 'n_clicks'),
142
  State('upload-pdf', 'contents'),
143
  State('upload-pdf', 'filename'),
 
146
  )
147
  def split_pdf(n_clicks, contents, filename, ranges):
148
  if not contents or not ranges:
149
+ logger.warning("Split PDF clicked but no content or ranges provided")
150
  raise PreventUpdate
151
 
152
+ logger.info("Split PDF button clicked")
153
  ranges = [r for r in ranges if r] # Filter out empty ranges
154
+ logger.info(f"Processing {len(ranges)} ranges")
155
+
156
  thread = Thread(target=process_pdf, args=(contents, filename, ranges))
157
  thread.start()
158
 
159
+ return 0, True, "PDF splitting process started. Check console for detailed logs."
160
 
161
  @callback(
162
  Output('progress-bar', 'value', allow_duplicate=True),
163
  Output('download-button', 'disabled', allow_duplicate=True),
164
+ Output('log-output', 'children', allow_duplicate=True),
165
  Input('progress-bar', 'value'),
166
  prevent_initial_call=True
167
  )
168
  def update_progress(value):
169
  global progress
170
  if progress == 100:
171
+ logger.info("PDF splitting completed")
172
+ return 100, False, "PDF splitting completed. Click 'Download ZIP' to get your files."
173
  elif progress == -1:
174
+ logger.error("PDF splitting failed")
175
+ return 0, True, "Error occurred during PDF splitting. Check console for details."
176
  else:
177
+ return progress, True, f"Processing... {progress:.0f}% complete"
178
 
179
  @callback(
180
  Output("download-zip", "data"),
 
184
  def download_zip(n_clicks):
185
  global generated_file
186
  if generated_file is not None:
187
+ logger.info("Initiating ZIP file download")
188
  return dcc.send_bytes(generated_file, "split_pdfs.zip")
189
+ logger.warning("Download attempted but no file generated")
190
  raise PreventUpdate
191
 
192
  if __name__ == '__main__':
193
+ logger.info("Starting the Dash application...")
194
  app.run(debug=True, host='0.0.0.0', port=7860)
195
+ logger.info("Dash application has finished running.")