By Vasudev Ram
I've known about CherryPy, a minimalist Python web framework (originally created by Remi Delon), since its early days, and have tried it out some.
Recently I had the idea (*) of using CherryPy and my xtopdf PDF creation toolkit together, to serve PDF via a web app.
(*) I thought of it because of my earlier two posts, PDF in a Flask and PDF in a Bottle.
The difference between the Flask and Bottle apps and this CherryPy app, is that the former two use a form to submit the text to be converted to PDF, whereas this app lets you upload a file to convert to PDF. Here's the code for PDF in a CherryPy (pdf_cherry.py):
# pdf_cherry.py
# Author: Vasudev Ram - http://www.dancingbison.com
# Program to generate PDF using CherryPy and xtopdf.
# Requires Reportlab v1.21 open source version.
# Written using CherryPy 3.2.4 and Python 2.7.5.
import os
from PDFWriter import PDFWriter
from file_utils import change_file_ext
from textwrap import TextWrapper
import os
import cherrypy
from cherrypy.lib.static import serve_file
class Root(object):
pass
class Upload(object):
def index(self):
return """
<html><head><title>PDF in a CherryPy</title></head><body>
<h3>PDF in a CherryPy</h3>
<h4>Upload a text file to convert to PDF.</h4>
<form action="text_to_pdf" method="post" enctype="multipart/form-data">
filename: <input type="file" name="uploadFile" /><br/>
<input type="submit"/>
</form>
</body></html>
"""
index.exposed = True
def text_to_pdf(self, uploadFile):
txt_filename = uploadFile.filename
pdf_filename = change_file_ext(txt_filename, ".txt", ".pdf")
pw = PDFWriter(pdf_filename)
pw.setFont("Courier", 10)
pw.setHeader("Text file: " + txt_filename + \
" PDF file: " + pdf_filename)
pw.setFooter("Generated by CherryPy, xtopdf and Reportlab")
wrapper = TextWrapper(width = 120, drop_whitespace = True,
break_long_words = True)
for lin in uploadFile.file.readlines():
lines = wrapper.wrap(lin)
for lin2 in lines:
pw.writeLine(lin)
pw.close()
respons = "<html><head><title>PDF in a CherryPy</title></head>"
respons += "<body><h3>PDF in a CherryPy</h3>"
respons += "Text file: " + txt_filename + "<br/>"
respons += 'PDF file: <a href="/download/?filepath=' + os.getcwd() + \
"\\" + pdf_filename + '">' + \
pdf_filename + '</a><br/>'
respons += "</body></html>"
return respons
text_to_pdf.exposed = True
class Download:
def index(self, filepath):
return serve_file(filepath, "application/x-download", "attachment")
index.exposed = True
def main():
root = Root()
root.upload = Upload()
root.download = Download()
cherrypy.quickstart(root)
if __name__ == '__main__':
main()
# EOF
Run it with:
python pdf_cherry.pyThen go to localhost:8080/upload in your browser, select a text file to convert to PDF, and click Submit. If there are no errors, you'll get another page with a link to download the generated PDF.
Here's a screenshot of pdf_cherry.py eating its own dog food, sort of :-)
I'm adding pdf_cherry.py to my xtopdf project on Bitbucket. [Update: Done.]
See other posts about Python, xtopdf, CherryPy, and web servers on my blog.
(The xtopdf posts are a subset of the Python posts, since xtopdf is written in Python.)
Users of CherryPy include Hulu and Netflix.
- Vasudev Ram - Python training and consulting

Added error handling to the pdf_cherry.py code in my xtopdf project on Bitbucket.
ReplyDeletextopdf.
I'm not updating the post above, but readers can get the updated code from Bitbucket.