Skip to content

Commit

Permalink
Merge pull request #5 from kimdv/kimdv/Vapor-3
Browse files Browse the repository at this point in the history
Updated to support Vapor 3
  • Loading branch information
bygri authored May 13, 2019
2 parents 0ea8d47 + e9768b3 commit 454a8a1
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 226 deletions.
102 changes: 0 additions & 102 deletions Package.pins

This file was deleted.

19 changes: 18 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
// swift-tools-version:4.2
import PackageDescription

let package = Package(
name: "wkhtmltopdf",
products: [
.library(
name: "wkhtmltopdf",
targets: ["wkhtmltopdf"]),
],
dependencies: [
.Package(url: "https://github.com/vapor/vapor.git", majorVersion: 2),
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
.package(url: "https://github.com/vapor/service.git", from: "1.0.0")
],
targets: [
.target(
name: "wkhtmltopdf",
dependencies: [
"Service"
]),
.testTarget(
name: "wkhtmltopdfTests",
dependencies: ["wkhtmltopdf", "Vapor"]),
]
)
68 changes: 44 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
# wkhtmltopdf

![Swift](http://img.shields.io/badge/swift-3.1-brightgreen.svg)
![Vapor](http://img.shields.io/badge/vapor-2.0-brightgreen.svg)
![Swift](http://img.shields.io/badge/swift-4.2-brightgreen.svg)
![Vapor](http://img.shields.io/badge/vapor-3.0-brightgreen.svg)
![Travis](https://travis-ci.org/vapor-community/wkhtmltopdf.svg?branch=master)

Vapor 2 library for converting HTML (Leaf or otherwise) into PDF files using
Vapor 3 library for converting HTML (Leaf or otherwise) into PDF files using
[wkhtmltopdf](http://wkhtmltopdf.org/).

## Getting Started

Add the following in your `Package.swift` file
```Swift
.package(url: "https://github.com/vapor-community/wkhtmltopdf.git", from: "2.0.0"),
```

## 📘 Overview

First, install [wkhtmltopdf](http://wkhtmltopdf.org/downloads.html). This
Expand All @@ -15,31 +22,44 @@ library is tested on version 0.12.4. Your binary should be installed at
installed correctly.

To create a PDF, create and configure a `Document`, add one or more `Page`s,
and then call `generatePDF()`. Here is a full example:
and then call `generatePDF(on: Request)`. Here is a full example:

```Swift
import wkhtmltopdf

// Create document. Margins in mm, can be set individually or all at once.
// If no margins are set, the default is 20mm.
let document = Document(margins: 15)
// Create a page from an HTML string.
let page1 = Page("<p>Page from direct HTML</p>")
// Create a page from a Leaf template.
let page2 = Page(drop, view: "page_from_leaf_template")
// Create a page from a Leaf template with Context variables.
let page3 = Page(drop, view: "page_from_leaf_template", [
"firstName": "Peter",
"lastName": "Pan"
])
// Add the pages to the document
document.pages = [page1, page2, page3]
// Render to a PDF
let pdf = try document.generatePDF()
// Now you can return the PDF as a response, if you want
let response = Response(status: .ok, body: .data(pdf))
response.headers["Content-Type"] = "application/pdf"
return response
func pdf(_ req: Request) -> Future<Response> {
// Create document. Margins in mm, can be set individually or all at once.
// If no margins are set, the default is 20mm.
let document = Document(margins: 15)
// Create a page from an HTML string.
let page1 = Page("<p>Page from direct HTML</p>")

// Create a page from a Leaf template.
let page2 = try req.view().render("page_from_leaf_template")

// Create a page from a Leaf template with Context variables.
let page3 = try req.view().render("page_from_leaf_template", [ "firstName": "Peter",
"lastName": "Pan"])
let pages = [ page2, page3].flatten(on: req)
.map { views in
return views.map { Page($0.data) }
}

return pages.flatMap { pages in
// Add the pages to the document
document.pages = [page1] + pages
// Render to a PDF
let pdf = try document.generatePDF(on: req)
// Now you can return the PDF as a response, if you want
return pdf.map { data -> Response in
let http = HTTPResponse(status: .ok,
headers: HTTPHeaders([("Content-Type", "application/pdf")]),
body: data)
return Response(http: http,
using: req)
}
}
}
```

In your Leaf file, you may want to load resources such as images, CSS
Expand Down
84 changes: 42 additions & 42 deletions Sources/wkhtmltopdf/Document+Generate.swift
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
import Foundation
import Core

#if os(Linux) && !swift(>=3.1)
typealias Process = Task
#endif
import Service

extension Document {

public func generatePDF() throws -> Bytes {
// Create the temp folder if it doesn't already exist
let workDir = "/tmp/vapor-wkhtmltopdf"
try FileManager().createDirectory(atPath: workDir, withIntermediateDirectories: true)
// Save input pages to temp files, and build up args to wkhtmltopdf
var wkArgs: [String] = [
"--zoom", Document.zoom,
"--quiet",
"-s", paperSize,
"-T", "\(topMargin)mm",
"-R", "\(rightMargin)mm",
"-B", "\(bottomMargin)mm",
"-L", "\(leftMargin)mm",
]
let fm = DataFile(workDir: workDir)
let pageFiles: [String] = try pages.map { page in
let fileName = "\(workDir)/\(UUID().uuidString).html"
try fm.write(page.content, to: fileName)
return fileName
}
defer {
pageFiles.forEach { path in
try? fm.delete(at: path)
}
}
wkArgs += pageFiles
// Call wkhtmltopdf and retrieve the result data
let wk = Process()
let stdout = Pipe()
wk.launchPath = "/usr/local/bin/wkhtmltopdf"
wk.arguments = wkArgs
wk.arguments?.append("-") // output to stdout
wk.standardOutput = stdout
wk.launch()
let pdf = stdout.fileHandleForReading.readDataToEndOfFile()
return pdf.makeBytes()
}
public func generatePDF(on container: Container) throws -> Future<Data> {
let sharedThreadPool = try container.make(BlockingIOThreadPool.self)

return sharedThreadPool.runIfActive(eventLoop: container.eventLoop) { () -> Data in
let fileManager = FileManager.default
// Create the temp folder if it doesn't already exist
let workDir = "/tmp/vapor-wkhtmltopdf"
try fileManager.createDirectory(atPath: workDir, withIntermediateDirectories: true)
// Save input pages to temp files, and build up args to wkhtmltopdf
var wkArgs: [String] = [
"--zoom", self.zoom,
"--quiet",
"-s", self.paperSize,
"-T", "\(self.topMargin)mm",
"-R", "\(self.rightMargin)mm",
"-B", "\(self.bottomMargin)mm",
"-L", "\(self.leftMargin)mm",
]

let pageFiles: [String] = try self.pages.map { page in
let name = UUID().uuidString + ".html"
let filename = "\(workDir)/\(name)"
try page.content.write(to: URL(fileURLWithPath: filename))
return filename
}
defer {
try? pageFiles.forEach(fileManager.removeItem)
}

wkArgs += pageFiles
// Call wkhtmltopdf and retrieve the result data
let wk = Process()
let stdout = Pipe()
wk.launchPath = "/usr/local/bin/wkhtmltopdf"
wk.arguments = wkArgs
wk.arguments?.append("-") // output to stdout
wk.standardOutput = stdout
wk.launch()
let pdf = stdout.fileHandleForReading.readDataToEndOfFile()
return pdf
}
}
}
33 changes: 16 additions & 17 deletions Sources/wkhtmltopdf/Document.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
public class Document {

// This may need changing across different platforms and deployments.
static var zoom: String = "1.3"
let zoom: String
let topMargin: Int
let rightMargin: Int
let bottomMargin: Int
let leftMargin: Int

let topMargin: Int
let rightMargin: Int
let bottomMargin: Int
let leftMargin: Int
let paperSize: String

let paperSize: String

public var pages: [Page] = []

public init(size: String = "A4", margins all: Int? = nil, top: Int? = nil, right: Int? = nil, bottom: Int? = nil, left: Int? = nil) {
paperSize = size
topMargin = all ?? top ?? 20
rightMargin = all ?? right ?? 20
bottomMargin = all ?? bottom ?? 20
leftMargin = all ?? left ?? 20
}
public var pages: [Page] = []

public init(size: String = "A4", zoom: String? = nil, margins all: Int? = nil, top: Int? = nil, right: Int? = nil, bottom: Int? = nil, left: Int? = nil) {
self.zoom = zoom ?? "1.3"
paperSize = size
topMargin = all ?? top ?? 20
rightMargin = all ?? right ?? 20
bottomMargin = all ?? bottom ?? 20
leftMargin = all ?? left ?? 20
}

}
13 changes: 0 additions & 13 deletions Sources/wkhtmltopdf/Page+View.swift

This file was deleted.

18 changes: 8 additions & 10 deletions Sources/wkhtmltopdf/Page.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import Bits
import Foundation

public struct Page {
let content: Data

let content: Bytes

public init(_ content: Bytes) {
self.content = content
}

public init(_ content: String) {
self.content = content.makeBytes()
}
public init(_ content: Data) {
self.content = content
}

public init(_ content: String) {
self.content = Data(content.utf8)
}
}
Loading

0 comments on commit 454a8a1

Please sign in to comment.