fabriquedoc-backend/main.py
Francois Pelletier 7d0eeff739 Initial commit
2022-12-28 00:04:27 -05:00

115 lines
3.7 KiB
Python

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