Building a PDF Splitter Web Application with Flask and PyPDF2- Part4

Vivekjainmaiet
3 min readApr 28, 2024

--

Introduction: In the previous steps of our tutorial, we laid the groundwork for our PDF splitter web application by setting up the Flask project structure, creating HTML templates, and implementing form submission handling and PDF processing. Now, in this part, we’ll finalize our application by generating download links for the split and merged PDF files, displaying success/error messages, and adding finishing touches to enhance the user experience.

Generating Download Links

After splitting and merging the PDF files, we’ll generate download links for the split and merged files, allowing users to download the processed PDFs directly from the application.

# Generate download links for split PDF files
split_download_links = []
for r in ranges:
start, end = map(int, r.split('-'))
filename = f"{start}-{end}-{file_name}.pdf"
split_file_path = os.path.join(output_dir, filename)
if not os.path.exists(split_file_path):
return render_template('error.html', message=f'File {split_file_path} does not exist')
split_download_links.append(f"download/split/{filename}")

Displaying Success Message

Once the PDF files have been processed successfully, we’ll render a success message to the user along with the download links for the split files.

return render_template('success.html', split_download_links=split_download_links)

Handling Errors

In case of any errors during the PDF processing or file manipulation, we’ll render an error message to the user, providing details about the encountered error.

except Exception as e:
return render_template('error.html', message=str(e))

Final app.py code

import os
from flask import Flask, render_template, request

from PyPDF2 import PdfReader, PdfWriter

app = Flask(__name__)
app.config['DOWNLOAD_FOLDER'] = 'downloads'


@app.route('/')
def index():
return render_template('index.html')


@app.route('/split', methods=['POST'])
def split():
try:
# Get the uploaded PDF file
pdf_file = request.files['pdf_file']

# Check if a file was uploaded
if not pdf_file:
return render_template('error.html', message='No file selected')

# Check if file format is supported
if pdf_file.content_type != 'application/pdf':
return render_template('error.html', message='Unsupported file format')

# Get the page ranges to split the PDF into
ranges = request.form.get('ranges')

# Check if page range is provided
if not ranges:
return render_template('error.html', message='Page range not provided')

# Get the page ranges to split the PDF into
ranges = request.form['ranges'].split(',')

# Create a directory to store the split files
output_dir = os.path.join(app.config['DOWNLOAD_FOLDER'], 'split')
if not os.path.exists(output_dir):
os.makedirs(output_dir)

file_name = os.urandom(16).hex()

# Split the PDF file into separate files based on the provided page ranges
with open(os.path.join(output_dir, 'output.pdf'), 'wb') as output:
input_pdf = PdfReader(pdf_file)
output_pdf = PdfWriter()

for r in ranges:
start, end = map(int, r.split('-'))
# Check if the range is valid for the input PDF
if end > len(input_pdf.pages):
return render_template('error.html', message=f'Page range {r} is out of range for the input PDF')
for i in range(start - 1, end):
if i < len(input_pdf.pages):
output_pdf.add_page(input_pdf.pages[i])

with open(os.path.join(output_dir, f"{start}-{end}-{file_name}.pdf"), 'wb') as f:
output_pdf.write(f)
output_pdf = PdfWriter()

# Generate download links for split PDF files
split_download_links = []
for r in ranges:
start, end = map(int, r.split('-'))
filename = f"{start}-{end}-{file_name}.pdf"
split_file_path = os.path.join(output_dir, filename)
if not os.path.exists(split_file_path):
return render_template('error.html', message=f'File {split_file_path} does not exist')
split_download_links.append(f"download/split/{filename}")

return render_template('success.html', split_download_links=split_download_links)

except Exception as e:
return render_template('error.html', message=str(e))


if __name__ == "__main__":
app.run(debug=True)

Testing and Deployment

Finally, we’ll test our PDF splitter application to ensure everything works as expected by running app.py.

Conclusion:

By following this part1 to part 4, we’ve completed our PDF splitter web application with Flask and PyPDF2. Users can now upload a PDF file, specify page ranges for splitting, and download the split files seamlessly. Deploying the application will make it accessible to users, streamlining their document management workflow. With these steps completed, you’re ready to take your PDF splitter application live and help users efficiently manage their PDF files.

--

--