ABDALLALSWAITI commited on
Commit
09084eb
·
verified ·
1 Parent(s): 3d135eb

Update api.py

Browse files
Files changed (1) hide show
  1. api.py +7 -194
api.py CHANGED
@@ -98,7 +98,8 @@ async def root():
98
  "endpoints": {
99
  "POST /convert": "Convert HTML to PDF (file upload)",
100
  "POST /convert-text": "Convert HTML text to PDF",
101
- "GET /health": "Health check"
 
102
  }
103
  }
104
 
@@ -136,203 +137,15 @@ async def convert_file(
136
  pdf_bytes = convert_html_to_pdf(html_content, aspect_ratio)
137
 
138
  # Return PDF file
 
 
 
 
139
  return Response(
140
  content=pdf_bytes,
141
  media_type="application/pdf",
142
  headers={
143
- "Content-Disposition": f"attachment; filename={file.filename.replace('.html', '.pdf').replace('.htm', '.pdf')}"
144
- }
145
- )
146
-
147
- except Exception as e:
148
- raise HTTPException(status_code=500, detail=f"Conversion failed: {str(e)}")
149
-
150
- @app.post("/convert-text")
151
- async def convert_text(
152
- html: str = Form(...),
153
- aspect_ratio: str = Form(default="9:16"),
154
- return_base64: bool = Form(default=False)
155
- ):
156
- """
157
- Convert HTML text to PDF
158
-
159
- - **html**: HTML content as string
160
- - **aspect_ratio**: Page orientation (16:9, 1:1, or 9:16)
161
- - **return_base64**: If true, returns base64 encoded PDF in JSON
162
- """
163
- if aspect_ratio not in ["16:9", "1:1", "9:16"]:
164
- raise HTTPException(status_code=400, detail="Invalid aspect ratio. Use: 16:9, 1:1, or 9:16")
165
-
166
- try:
167
- # Convert to PDF
168
- pdf_bytes = convert_html_to_pdf(html, aspect_ratio)
169
-
170
- if return_base64:
171
- # Return as JSON with base64 encoded PDF
172
- pdf_base64 = base64.b64encode(pdf_bytes).decode('utf-8')
173
- return JSONResponse(content={
174
- "success": True,
175
- "pdf_base64": pdf_base64,
176
- "size_bytes": len(pdf_bytes)
177
- })
178
- else:
179
- # Return PDF file directly
180
- return Response(
181
- content=pdf_bytes,
182
- media_type="application/pdf",
183
- headers={
184
- "Content-Disposition": "attachment; filename=converted.pdf"
185
- }
186
- )
187
-
188
- except Exception as e:
189
- raise HTTPException(status_code=500, detail=f"Conversion failed: {str(e)}")
190
-
191
- if __name__ == "__main__":
192
- import uvicorn
193
- uvicorn.run(app, host="0.0.0.0", port=7860)from fastapi import FastAPI, File, UploadFile, Form, HTTPException
194
- from fastapi.responses import Response, JSONResponse
195
- from fastapi.middleware.cors import CORSMiddleware
196
- import tempfile
197
- import shutil
198
- import os
199
- import subprocess
200
- import base64
201
- from pathlib import Path
202
-
203
- app = FastAPI(
204
- title="HTML to PDF API",
205
- description="Convert HTML to PDF using Puppeteer",
206
- version="1.0.0"
207
- )
208
-
209
- # Enable CORS
210
- app.add_middleware(
211
- CORSMiddleware,
212
- allow_origins=["*"],
213
- allow_credentials=True,
214
- allow_methods=["*"],
215
- allow_headers=["*"],
216
- )
217
-
218
- def convert_html_to_pdf(html_content: str, aspect_ratio: str):
219
- """Convert HTML content to PDF"""
220
- temp_dir = None
221
- try:
222
- temp_dir = tempfile.mkdtemp()
223
-
224
- # Style injection for better PDF rendering
225
- style_injection = """
226
- <style>
227
- @page { margin: 0; }
228
- * {
229
- -webkit-print-color-adjust: exact !important;
230
- print-color-adjust: exact !important;
231
- color-adjust: exact !important;
232
- }
233
- body {
234
- -webkit-print-color-adjust: exact !important;
235
- print-color-adjust: exact !important;
236
- }
237
- </style>
238
- """
239
-
240
- if '</head>' in html_content:
241
- html_content = html_content.replace('</head>', style_injection + '</head>')
242
- elif '<body' in html_content:
243
- html_content = html_content.replace('<body', style_injection + '<body', 1)
244
- else:
245
- html_content = style_injection + html_content
246
-
247
- # Save HTML to temp file
248
- html_file = os.path.join(temp_dir, "input.html")
249
- with open(html_file, 'w', encoding='utf-8') as f:
250
- f.write(html_content)
251
-
252
- # Get puppeteer script path
253
- script_dir = os.path.dirname(os.path.abspath(__file__))
254
- puppeteer_script = os.path.join(script_dir, 'puppeteer_pdf.js')
255
-
256
- # Run conversion
257
- result = subprocess.run(
258
- ['node', puppeteer_script, html_file, aspect_ratio],
259
- capture_output=True,
260
- text=True,
261
- timeout=60,
262
- cwd=script_dir
263
- )
264
-
265
- if result.returncode != 0:
266
- raise Exception(f"PDF conversion failed: {result.stderr}")
267
-
268
- pdf_file = html_file.replace('.html', '.pdf')
269
-
270
- if not os.path.exists(pdf_file):
271
- raise Exception("PDF file was not generated")
272
-
273
- with open(pdf_file, 'rb') as f:
274
- pdf_bytes = f.read()
275
-
276
- shutil.rmtree(temp_dir, ignore_errors=True)
277
- return pdf_bytes
278
-
279
- except Exception as e:
280
- if temp_dir:
281
- shutil.rmtree(temp_dir, ignore_errors=True)
282
- raise e
283
-
284
- @app.get("/")
285
- async def root():
286
- """API root endpoint"""
287
- return {
288
- "message": "HTML to PDF Conversion API",
289
- "version": "1.0.0",
290
- "endpoints": {
291
- "POST /convert": "Convert HTML to PDF (file upload)",
292
- "POST /convert-text": "Convert HTML text to PDF",
293
- "GET /health": "Health check"
294
- }
295
- }
296
-
297
- @app.get("/health")
298
- async def health_check():
299
- """Health check endpoint"""
300
- return {"status": "healthy", "service": "html-to-pdf-api"}
301
-
302
- @app.post("/convert")
303
- async def convert_file(
304
- file: UploadFile = File(...),
305
- aspect_ratio: str = Form(default="9:16")
306
- ):
307
- """
308
- Convert uploaded HTML file to PDF
309
-
310
- - **file**: HTML file to convert
311
- - **aspect_ratio**: Page orientation (16:9, 1:1, or 9:16)
312
- """
313
- if not file.filename.lower().endswith(('.html', '.htm')):
314
- raise HTTPException(status_code=400, detail="File must be HTML (.html or .htm)")
315
-
316
- if aspect_ratio not in ["16:9", "1:1", "9:16"]:
317
- raise HTTPException(status_code=400, detail="Invalid aspect ratio. Use: 16:9, 1:1, or 9:16")
318
-
319
- try:
320
- # Read HTML content
321
- content = await file.read()
322
- try:
323
- html_content = content.decode('utf-8')
324
- except UnicodeDecodeError:
325
- html_content = content.decode('latin-1')
326
-
327
- # Convert to PDF
328
- pdf_bytes = convert_html_to_pdf(html_content, aspect_ratio)
329
-
330
- # Return PDF file
331
- return Response(
332
- content=pdf_bytes,
333
- media_type="application/pdf",
334
- headers={
335
- "Content-Disposition": f"attachment; filename={file.filename.replace('.html', '.pdf').replace('.htm', '.pdf')}"
336
  }
337
  )
338
 
 
98
  "endpoints": {
99
  "POST /convert": "Convert HTML to PDF (file upload)",
100
  "POST /convert-text": "Convert HTML text to PDF",
101
+ "GET /health": "Health check",
102
+ "GET /docs": "API documentation (Swagger UI)"
103
  }
104
  }
105
 
 
137
  pdf_bytes = convert_html_to_pdf(html_content, aspect_ratio)
138
 
139
  # Return PDF file
140
+ filename = file.filename.replace('.html', '.pdf').replace('.htm', '.pdf')
141
+ if not filename.endswith('.pdf'):
142
+ filename += '.pdf'
143
+
144
  return Response(
145
  content=pdf_bytes,
146
  media_type="application/pdf",
147
  headers={
148
+ "Content-Disposition": f"attachment; filename={filename}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  }
150
  )
151