-- | Utilities for serving PDF from Yesod -- Uses and depends on command line utility wkhtmltopdf to render PDF from HTML module Yesod.Content.PDF where import Prelude import Yesod.Core.Content import Data.ByteString import Text.Blaze.Html import Text.Blaze.Html.Renderer.String import Blaze.ByteString.Builder.ByteString import System.Process import System.IO.Temp import System.IO import Network.URI import Data.Conduit newtype PDF = PDF ByteString -- | Provide MIME type "application/pdf" as a ContentType for Yesod typePDF :: ContentType typePDF = "application/pdf" instance HasContentType PDF where getContentType _ = typePDF instance ToTypedContent PDF where toTypedContent = TypedContent typePDF . toContent instance ToContent PDF where toContent (PDF bs) = ContentSource $ do yield $ Chunk $ fromByteString bs -- | Use wkhtmltopdf to render a PDF given the URI pointing to an HTML document uri2PDF :: URI -> IO PDF uri2PDF uri = withSystemTempFile "output.pdf" $ uri2PDF' uri where uri2PDF' :: URI -> FilePath -> Handle -> IO PDF uri2PDF' uri' tempPDFFile tempHandle = do hClose tempHandle (_,_,_, pHandle) <- createProcess (proc "wkhtmltopdf" ["--quiet", show uri', tempPDFFile]) _ <- waitForProcess pHandle PDF <$> Data.ByteString.readFile tempPDFFile -- | Use wkhtmltopdf to render a PDF from an HTML (Text.Blaze.Html) type html2PDF :: Html -> IO PDF html2PDF html = withSystemTempFile "output.pdf" (html2PDF' html) where html2PDF' :: Html -> FilePath -> Handle -> IO PDF html2PDF' html' tempPDFFile tempPDFHandle = do hClose tempPDFHandle withSystemTempFile "input.html" $ \tempHtmlFile tempHtmlHandle -> do System.IO.hPutStrLn tempHtmlHandle $ renderHtml html' hClose tempHtmlHandle (_,_,_, pHandle) <- createProcess (proc "wkhtmltopdf" ["--quiet", tempHtmlFile, tempPDFFile]) _ <- waitForProcess pHandle PDF <$> Data.ByteString.readFile tempPDFFile