import os import subprocess from pathlib import Path import pypdf from flask import Flask, flash, redirect, render_template, request, url_for from werkzeug.utils import secure_filename UPLOAD_FOLDER = str(Path(__file__).parent / "uploads") ALLOWED_EXTENSIONS = {"pdf"} PRINTER_NAME = "HL-2270DW_series" MAX_PAGES = 10 app = Flask(__name__) app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER app.config["SECRET_KEY"] = os.urandom(24) app.config["MAX_CONTENT_LENGTH"] = 16 * 1024 * 1024 def allowed_file(filename): return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS def get_pdf_page_count(filepath): try: with open(filepath, "rb") as f: reader = pypdf.PdfReader(f) return len(reader.pages) except Exception as e: app.logger.error(f"Could not read PDF pages: {e}") return None @app.route("/", methods=["GET", "POST"]) def upload_and_print(): if request.method == "POST": if "file" not in request.files: flash("No file part in the request.", "error") return redirect(request.url) file = request.files["file"] if file.filename == "": flash("No file selected. Please choose a PDF to print.", "error") return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True) filepath = os.path.join(app.config["UPLOAD_FOLDER"], filename) file.save(filepath) try: page_count = get_pdf_page_count(filepath) if page_count is None: flash( "Could not process the PDF file. It might be corrupt.", "error" ) return redirect(request.url) if page_count > MAX_PAGES: flash( f"Error: File has {page_count} pages. The maximum allowed is {MAX_PAGES}.", "error", ) return redirect(request.url) app.logger.info( f"Sending '{filename}' ({page_count} pages) to printer '{PRINTER_NAME}'" ) command = ["lp", "-d", PRINTER_NAME, filepath] result = subprocess.run( command, capture_output=True, text=True, check=True ) app.logger.info(f"lp command stdout: {result.stdout}") flash(f"Success! '{filename}' has been sent to the printer.", "success") except subprocess.CalledProcessError as e: app.logger.error(f"Error printing file: {e}") app.logger.error(f"lp command stderr: {e.stderr}") flash( "Error sending file to printer. The printer may be offline or misconfigured.", "error", ) except Exception as e: app.logger.error(f"An unexpected error occurred: {e}") flash("An unexpected server error occurred.", "error") finally: if os.path.exists(filepath): os.remove(filepath) app.logger.info(f"Cleaned up temporary file: {filepath}") return redirect(url_for("upload_and_print")) else: flash("Invalid file type. Please upload a PDF file.", "error") return redirect(request.url) return render_template("index.html", printer_name=PRINTER_NAME, max_pages=MAX_PAGES) if __name__ == "__main__": app.run(host="127.0.0.1", port=57928, debug=False)