import datetime import logging from fastapi import FastAPI from fastapi.responses import FileResponse from pydantic import BaseModel import pypandoc import json import httpx from fastapi.testclient import TestClient import os from wand.image import Image from wand.color import Color import shutil class DocumentSpecs(BaseModel): format: str style: str linkcolor: str tocdepth: int pdfengine: str content: str fontsize: int paperwidth: int paperheight: int margin: int extension: str def convert_pdf_jpg(filename, output_path, resolution=300): """ Convert a PDF into images. All the pages will give a single png file with format: {pdf_filename}-{page_number}.png The function removes the alpha channel from the image and replace it with a white background. """ all_pages = Image(filename=filename, resolution=resolution) for i, page in enumerate(all_pages.sequence): with Image(page) as img: img.format = 'jpg' img.background_color = Color('black') #img.alpha_channel = 'remove' image_filename = os.path.splitext(os.path.basename(filename))[0] image_filename = '{}-{}.jpg'.format(image_filename, i) image_filename = os.path.join(output_path, image_filename) img.save(filename=image_filename) app = FastAPI() @app.get("/generer/") async def generer(specs: DocumentSpecs): header_file = f'{os.getcwd()}/styles/{specs.style}/{specs.format}/header.tex' cover_file = f'{os.getcwd()}/styles/{specs.style}/{specs.format}/cover.tex' datef = datetime.datetime.now().strftime("%m-%d-%Y") output_file = f"./{specs.style}-{specs.format}-{datef}-output.pdf" filters = [] pdoc_args = [ f'--include-in-header={header_file}', f'--include-after-body={cover_file}', '--listings', '--dpi=300', f'--toc-depth={specs.tocdepth}', f'--pdf-engine={specs.pdfengine}', '-V',f'linkcolor={specs.linkcolor}', '-V',f'fontsize={specs.fontsize}pt', '-V',f'geometry:paperwidth={specs.paperwidth/300}in', '-V',f'geometry:paperheight={specs.paperheight/300}in', '-V',f'geometry:margin={specs.margin/300}in' ] try: logging.info("Dossier courant = " + os.getcwd()) result = pypandoc.convert_text(source=specs.content, to='pdf', format='markdown+implicit_figures+smart', encoding='utf-8', extra_args=pdoc_args, filters=filters, cworkdir=os.getcwd(), outputfile=output_file ) except RuntimeError as rerr: logging.exception(rerr) except OSError as oerr: logging.exception(oerr) if specs.extension=="zip": zip_filename = os.path.splitext(os.path.basename(output_file))[0] png_output_dir = "./png_output" if not os.path.exists(png_output_dir): os.mkdir(png_output_dir) try: convert_pdf_jpg(output_file, png_output_dir, resolution=300) shutil.make_archive(zip_filename, 'zip', png_output_dir) shutil.rmtree(png_output_dir) except Exception as e: logging.exception(e) return FileResponse(zip_filename+".zip") elif specs.extension=="pdf": return FileResponse(output_file) else: return 0 client = TestClient(app) def test_generer(): test_json = json.read("test.json") response = client.get("/generer/", json=test_json) assert response.status_code == 200