HyPDF

This add-on is operated by HyPDF

Your Swiss Army knife for working with PDF.

HyPDF

Last Updated: 05 April 2014

Table of Contents

HyPDF is an add-on that provides you the full set of tools for working with PDF docuemnts. With HyPDF you can:

  • Create beautiful and complex PDF documents using familiar HTML, CSS and JavaScript.
  • Collect exhaustive information about any PDF file, such as number of pages, author, PDF version and so on.
  • Transform PDF files to the plain text.
  • Extract certain pages from whole PDF file.
  • Merge two PDF files into one.

Moreover, HyPDF can upload created PDFs to your own AWS S3 bucket for you.

HyPDF is accessible via a simple API and has supported client library for Ruby, though it can be used by any language with support for making HTTP requests.

Provisioning the add-on

HyPDF can be attached to a Heroku application via the CLI:

A list of all plans available can be found here

$ heroku addons:add hypdf
-----> Adding hypdf to sharp-mountain-4005... done, v18 (free)

Once HyPDF has been added the HYPDF_USER and HYPDF_PASSWORD settings will be available in the app configuration and will contain user name and password needed to use HyPDF API. This can be confirmed using the heroku config:get command.

$ heroku config:get HYPDF_USER
app123@heroku.com

Environment setup

After provisioning the add-on it’s necessary to locally replicate the config vars so your development environment can operate against the service.

Though less portable it’s also possible to set local environment variables using export HYPDF_USER=123@heroku.com

Use Foreman to reliably configure and run the process formation specified in your app’s Procfile. Foreman reads configuration variables from an .env file. Use the following command to add the HyPDF variables values retrieved from heroku config to .env.

$ heroku config -s | grep HYPDF_ >> .env
$ more .env

Credentials and other sensitive configuration values should not be committed to source-control. In Git exclude the .env file with: echo .env >> .gitignore.

Using with Ruby/Rails

Ruby/Rails applications will need to add the following entry into their Gemfile specifying the HyPDF client library.

gem 'hypdf', '~> 1.0.2'

Update application dependencies with bundler.

$ bundle install

Call htmltopdf method with your HTML/URL and optional parameters and get your document directly. Tip: use test option during the development.

@hypdf = HyPDF.htmltopdf(
    '<html><body><h1>Title</h1></body></html>',
    orientation: 'Landscape',
    copies: 2,
    # ... other options ...
)

# send PDF to user
send_data(
    @hypdf[:pdf],
    filename: "pdf_with_#{@hypdf[:pages]}_pages.pdf",
    type: 'application/pdf'
)

You can find rails example application on Github.

Using with other languages

HyPDF is accessible via a HTTP API described in API reference section. HYPDF_USER and HYPDF_PASSWORD variables can be found in the heroku config output.

Python example (using flask and requests):

import requests
from flask import Flask
from flask import request
app = Flask(__name__)

# Make request to the HyPDF and upload the created file to the AWS S3 in an asynchronous style.
@app.route("/")
def index():
    params = {'user': 'HYPDF_USER', 'password': 'HYPDF_PASSWORD', 'test': 'true', 'content': '<html><body>Test</body</html>', 'bucket': 'hypdf_test', 'key': 'hypdf_test.pdf', 'public': 'true', 'callback': 'http://yoursite.com/pdf_complete'}
    r = requests.post('https://www.hypdf.com/htmltopdf', data=params)
    return r.json()['job_id']

# Get response from the HyPDF
@app.route("/pdf_complete", methods=['POST'])
def print_pdf_data():
    print 'job_id: ' + request.headers['hypdf-job-id']
    print 'number of pages: ' + request.headers['hypdf-pages']
    print 'url: ' + request.form['url']
    return 'ok'

if __name__ == "__main__":
    app.run()

Node.js example (using request):

var request = require('request'),
    fs = require("fs");

// Create PDF and upload it to AWS S3
request.post(
    'https://www.hypdf.com/htmltopdf',
    {
        json: {
            user: 'HYPDF_USER',
            password: 'HYPDF_PASSWORD',
            content: '<html><body><h1>Title</h1></body></html>',
            margin_left: '0.5in',
            grayscale: true,
            bucket: 'YOUR_BUCKET_NAME',
            key: 'some_file_name.pdf',
            public: true
        }
    },
    function (error, response, body) {
        if (!error && response.statusCode == 200) {
            console.log('Public URL: ', body.url);
            console.log('Number of pages: ', response.headers['hypdf-pages']);
        }
    }
);

Also there is unofficial Node.js wrapper for the HyPDF API.

API reference

htmltopdf

Ruby:

@hypdf = HyPDF.htmltopdf(
    '<html><body><h1>Title</h1></body></html>',
    orientation: 'Landscape',
    copies: 2,
    # ... other options ...
)
# => {pdf: BINARY_PDF_DATA, pages: 1, page_size: "792 x 612 pts (letter)", pdf_version: 1.4}

Other languages:

URL: 'https://www.hypdf.com/htmltopdf'
Method: 'POST'
Content-Type: 'application/json'
Parameters: {content: 'HTML', user: 'HYPDF_USER', password: 'HYPDF_PASSWORD'}
Result: 'BINARY_PDF_DATA'

Optional parameters can be passed directly or through a special meta tag in the HTML content:

<meta name="hypdf-option_name" content="value" />

Optional parameters:

Option name Possible value Description
test true, false Use test mode.
bucket String Upload created PDF to this AWS S3 bucket.
key String File name.
public true, false Grant everyone read access to uploaded file.
callback String (URL) Create PDF in the background and post results to this URL.
disable_links true If present, render plain text instead of links.
no_collate true If present, do not collate when printing multiple copies
copies Integer Number of copies to print into the pdf file (default 1)
grayscale true If present, PDF will be generated in grayscale
lowquality true Generates lower quality pdf/ps. Useful to shrink the result document space
dpi Integer Change the dpi explicitly
image_dpi Integer When embedding images scale them down to this dpi (default 600)
image_quality Integer When jpeg compressing images use this quality (default 94)
margin_bottom String (“0.5in”, “15mm”, “2cm” etc) Set the page bottom margin (default “0.75in”)
margin_left String (“0.5in”, “15mm”, “2cm” etc) Set the page left margin (default “0.75in”)
margin_right String (“0.5in”, “15mm”, “2cm” etc) Set the page right margin (default “0.75in”)
margin_top String (“0.5in”, “15mm”, “2cm” etc) Set the page top margin (default “0.75in”)
orientation Landscape, Portrait Set orientation (default “Portrait”)
page_height String (“8.27in”, “297mm”, “21cm” etc) Page height
page_width String (“8.27in”, “297mm”, “21cm” etc) Page width
page_size A0..B10, C5E, Comm10E, DLE, Executive, Folio, Ledger, Legal, Letter, Tabloid Set paper size (default “Letter”)
title String The title of the generated pdf file (The title of the first document is used if not specified)
no_background true If present, do not print background
cookie String (“name value”) Set an additional cookie (repeatable)
custom_header String (“name value”) Set an additional HTTP header (repeatable)
no_custom_header_propagation true If present, do not add HTTP headers specified by custom_header for each resource request.
encoding String Set the default text encoding, for input (default “UTF-8”)
no_images true If present, do not load or print images
disable_javascript true If present, do not allow web pages to run javascript
javascript_delay Integer Wait some milliseconds for javascript finish (default 200)
no_stop_slow_scripts true If present, do not Stop slow running javascripts
run_script String (code) Run this additional javascript after the page is done loading (repeatable)
minimum_font_size Integer Minimum font size
page_offset Integer Set the starting page number (default 0)
password String HTTP Authentication password
username String HTTP Authentication username
user_style_sheet String Specify a URL to user style sheet, to load with every page
window_status String Wait until window.status is equal to this string before rendering page
zoom Float Use this zoom factor (default 1)
header_left String Left aligned header text.
header_right String Right aligned header text.
header_center String Centered header text.
header_font_name String Set header font name (default Arial).
header_font_size Integer Set header font size (default 12).
header_line true Display line below the header.
header_html String (URL of HTML document) Adds a html header (overrides any other header_* options listed above).
header_spacing Float Spacing between header and content in mm (default 0).
footer_left String Left aligned footer text.
footer_right String Right aligned footer text.
footer_center String Centered footer text.
footer_font_name String Set footer font name (default Arial).
footer_font_size Integer Set footer font size (default 12).
footer_line true Display line above the footer.
footer_html String (URL of HTML document) Adds a html footer (overrides any other footer_* options listed above).
footer_spacing Float Spacing between content and footer in mm (default 0).
header_* options do not work in test mode.

jobstatus

Check background job status.

Ruby:

@hypdf = HyPDF.jobstatus(
    'ae19dafbb8d4880929d89af6' # your job ID
)
# => {"job_id"=>"ae19dafbb8d4880929d89af6", "status"=>"working"}

Other languages:

URL: 'https://www.hypdf.com/jobstatus'
Method: 'GET'
Content-Type: 'application/json'
Parameters: {job_id: 'JOB_ID', user: 'HYPDF_USER', password: 'HYPDF_PASSWORD'}
Result: 'json'

Possible statuses: waiting, working, complete, failed.

pdfinfo

Ruby:

@hypdf = HyPDF.pdfinfo(
    '/path/to/file.pdf' # or instance of File class
)
# => {"Title"=>"Everyday Rails Testing with RSpec", "Author"=>"Aaron Sumner", "Creator"=>"LaTeX with hyperref package", "Producer"=>"xdvipdfmx (0.7.8)", "CreationDate"=>"Fri Aug  2 05", "32"=>"50 2013", "Tagged"=>"no", "Pages"=>"150", "Encrypted"=>"no", "Page size"=>"612 x 792 pts (letter)", "Optimized"=>"no", "PDF version"=>"1.5"}

Other languages:

URL: 'https://www.hypdf.com/pdfinfo'
Method: 'POST'
Content-Type: 'multipart/form-data'
Parameters: {file: 'BINARY_PDF_DATA', user: 'HYPDF_USER', password: 'HYPDF_PASSWORD'}
Result: 'json'

pdftotext

Ruby:

@hypdf = HyPDF.pdftotext(
    '/path/to/file.pdf', # or instance of File class
    first_page: 2,
    last_page: 5,
    # ... other options ...
)
# => {text: "Everyday Rails Testing with RSpec\nA practical approach to test-driven..."}

Other languages:

URL: 'https://www.hypdf.com/pdftotext'
Method: 'POST'
Content-Type: 'multipart/form-data'
Parameters: {file: 'BINARY_PDF_DATA', user: 'HYPDF_USER', password: 'HYPDF_PASSWORD'}
Result: 'json'

Optional parameters:

Option name Possible value Description
first_page Integer First page to convert.
last_page Integer Last page to convert.
no_page_break true If present, don’t insert page breaks between pages.
crop_x Integer x-coordinate of the crop area top left corner.
crop_y Integer y-coordinate of the crop area top left corner.
crop_width Integer Width of crop area in pixels.
crop_height Integer Height of crop area in pixels.

pdfextract

Ruby:

@hypdf = HyPDF.pdfextract(
    '/path/to/file.pdf', # or instance of File class
    last_page: 5,
    # ... other options ...
)
# => {pdf: BINARY_PDF_DATA}

Other languages:

URL: 'https://www.hypdf.com/pdfextract'
Method: 'POST'
Content-Type: 'multipart/form-data'
Parameters: {file: 'BINARY_PDF_DATA', user: 'HYPDF_USER', password: 'HYPDF_PASSWORD'}
Result: 'BINARY_PDF_DATA'

Optional parameters:

Option name Possible value Description
first_page Integer First page to extract.
last_page Integer Last page to extract.
test true, false Use test mode.
bucket String Upload created PDF to this AWS S3 bucket.
key String File name.
public true, false Grant everyone read access to uploaded file.

pdfunite

Ruby:

@hypdf = HyPDF.pdfunite(
    '/path/to/file1.pdf', # or instance of File class
    '/path/to/file2.pdf', # or instance of File class
    '/path/to/file3.pdf', # or instance of File class
    # ... other files or options ...
)
# => {pdf: BINARY_PDF_DATA}

Other languages:

URL: 'https://www.hypdf.com/pdfunite'
Method: 'POST'
Content-Type: 'multipart/form-data'
Parameters: {file_1: 'BINARY_PDF_DATA', file_2: 'BINARY_PDF_DATA', file_3: ..., user: 'HYPDF_USER', password: 'HYPDF_PASSWORD'}
Result: 'BINARY_PDF_DATA'

Optional parameters:

Option name Possible value Description
test true, false Use test mode.
bucket String Upload created PDF to this AWS S3 bucket.
key String File name.
public true, false Grant everyone read access to uploaded file.

Test mode

During the development you may want to use the test mode. In this case HyPDF do not count against your daily document quota.

@hypdf = HyPDF.pdfunite(
    '/path/to/file1.pdf',
    '/path/to/file2.pdf',
    test: true,
    # ... other options ...
)

Uploading to AWS S3

HyPDF can upload created files to your AWS S3 bucket, but before you need to give permission HyPDF to do it.

  • Visit your AWS Security Credentials page
  • Copy Canonical User ID from “Account Identifiers” section
  • Add it to your HyPDF account via add-on dashboard
  • Log into AWS Console
  • Choose S3 service
  • Right click on the bucket you wish to give HyPDF permission to write to
  • From the context menu, click “Properties”
  • On properties panel select “Permissions” and click on “Add bucket policy” button
  • Paste the following policy into the dialog that appears (Replace YOUR_BUCKET_NAME with the name of the bucket you are adding this permission to)

Policy:

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "AddCannedAcl",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::495273932038:root"
      },
      "Action": [
        "s3:GetBucketAcl",
        "s3:PutObjectAcl",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::YOUR_BUCKET_NAME/*",
        "arn:aws:s3:::YOUR_BUCKET_NAME"
      ]
    }
  ]
}

After that you can use the bucket option in HyPDF methods:

@hypdf = HyPDF.htmltopdf(
    '<html><body><h1>Title</h1></body></html>',
    orientation: 'Landscape',
    # ... other options ...
    bucket: 'YOUR_BUCKET_NAME',
    key: 'some_file_name.pdf', # optional
    public: true # optional, generate public readable URL
)
# => { url: "https://s3.amazonaws.com/YOUR_BUCKET_NAME/some_file_name.pdf", pages: 1, page_size: "792 x 612 pts (letter)", pdf_version: 1.4, bucket: "YOUR_BUCKET_NAME", key: "some_file_name.pdf"}

Asynchronous creation

You don’t need to wait and block your application until the document is created, HyPDF can handle your files in asynchronous style. Just provide callback URL that will be called when PDF will be ready.

def create
    @hypdf = HyPDF.htmltopdf(
        '<html><body><h1>Title</h1></body></html>',
        orientation: 'Landscape',
        # ... other options ...
        callback: 'http://www.your-application.com/save_pdf_url',
        bucket: 'YOUR_BUCKET_NAME',
        key: 'some_file_name.pdf',
        public: true
    )

    # You can check job status in any time
    puts HyPDF.jobstatus(@hypdf[:job_id])
end

# POST /save_pdf_url
def save_pdf_url
    if params[:error]
        puts params[:message]
    else
        # PDF url
        puts params[:url]
        # Job ID
        puts request.headers['hypdf-job-id']
        # Number of pages
        puts request.headers['hypdf-pages']
    end
end

Performance notes and kwnon caveats

  • Try to not use external resources because their loading significantly increases the time of creation of your PDF document.
  • Place your styles and scripts within <style> and <script> tags instead of loading them using <link> tag.
  • Use the data URI to insert small images. There are many tools for converting images into data URI format (eg filetobase64.com).
  • Do not use grayscale JPEG images. Use GIF or PNG instead.
  • Do not apply “opacity” and “font-size” CSS properties to a same element. Use “background: rgba( 255, 0, 0, 0.5)” instead of “opacity” in this case.

Dashboard

The HyPDF dashboard allows you to check up your current balance, usage statistics and add-on news.

The dashboard can be accessed via the CLI:

$ heroku addons:open hypdf
Opening hypdf for sharp-mountain-4005…

or by visiting the Heroku apps web interface and selecting the application in question. Select HyPDF from the Add-ons menu.

Migrating between plans

Use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade hypdf:giga
-----> Upgrading hypdf:giga to sharp-mountain-4005... done, v18
Your plan has been updated to: hypdf:giga

Removing the add-on

HyPDF can be removed via the CLI.

This will destroy all associated data and cannot be undone!
$ heroku addons:remove hypdf
-----> Removing hypdf from sharp-mountain-4005... done, v20 (free)

Support

All HyPDF support and runtime issues should be submitted via on of the Heroku Support channels. Any non-support related issues or product feedback is welcome at support@hypdf.com.