Skip to content

feat: add batch PDF-to-PNG conversion endpoint β€” current implementation only converts the first page, forcing users to make N separate requests for an N-page PDFΒ #479

Description

@divyanshim27

πŸš€ Problem Statement

The README documents: "Convert PDF (first page) to PNG." The POST /convertPng endpoint in backend/blueprints/pdf.py uses PyMuPDF (fitz) to render only page = doc[0] β€” the first page β€” and returns a single PNG.

A user with a 10-page PDF who needs all pages as PNGs must submit 10 separate requests. This is:

  • Slow (10 round-trips vs 1)
  • Error-prone (no atomicity β€” page 7 might fail while 1-6 succeeded)
  • Not how file manipulation tools work (e.g., ImageMagick, LibreOffice batch-convert all pages)

Proposed Fix

Add a POST /convertPngBatch endpoint (respecting Project Rule 1: no disk storage) that returns a ZIP archive of all pages as PNGs, generated entirely in memory:

# backend/blueprints/pdf.py β€” new batch endpoint

import io
import zipfile
import fitz  # PyMuPDF
from flask import Blueprint, request, send_file

@pdf_bp.route('/convertPngBatch', methods=['POST'])
def convert_pdf_all_pages_to_png():
    """
    Convert all pages of an uploaded PDF to PNG images.
    Returns a ZIP archive (in memory, no disk storage) containing
    one PNG per page, named page_001.png, page_002.png, etc.
    """
    if 'file' not in request.files:
        return {'error': 'No file provided'}, 400

    file = request.files['file']
    if not file.filename.lower().endswith('.pdf'):
        return {'error': 'File must be a PDF'}, 415

    pdf_bytes = file.read()
    doc = fitz.open(stream=pdf_bytes, filetype='pdf')

    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
        for page_num in range(len(doc)):
            page = doc[page_num]
            mat = fitz.Matrix(2.0, 2.0)  # 2x scale for quality
            pix = page.get_pixmap(matrix=mat)
            png_bytes = pix.tobytes('png')
            zf.writestr(f'page_{page_num + 1:03d}.png', png_bytes)

    zip_buffer.seek(0)
    return send_file(
        zip_buffer,
        mimetype='application/zip',
        as_attachment=True,
        download_name='converted_pages.zip'
    )

This strictly follows Project Rules 1 and 2: all processing is in memory, no external APIs used.

Files to Modify

File Change
backend/blueprints/pdf.py Add POST /convertPngBatch endpoint
frontend/src/pages/PdfPng.jsx Add UI toggle for "Convert All Pages" mode
Readme.md Document the new /convertPngBatch endpoint

Suggested labels: enhancement, backend, frontend

I would like to work on this. Could you please assign it to me?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions