I coded a simple JSON web service, which converts any HTML input to PDF (using the excellent wkthmltopdf software). You can supply HTML code or an URI where to get it.

Using the powerful Mojolicious web framework (Mojolicious::Lite is enough for this application, actually) framework it's just roughly 100 lines of code for the whole thing:

#!/usr/bin/perl

# Pulls in strict and unicode_strings, but this
# program doesn't require perl 5.14 to work
use v5.14;

use Mojolicious::Lite;
use Path::Class;
use File::Temp;
use Mojo::UserAgent;
use MIME::Base64;

my $config = {
    wkh     => '/usr/local/bin/wkhtmltopdf',
    tmpdir  => '/tmp',
    auth    => 'maitai',
};

post '/' => sub {
    my $self = shift;
    
    my $args = $self->req->json;

    # Handle obvious error cases
    return $self->mkerror('invalid-JSON-content')
        if !defined $args;
    return $self->mkerror('invalid-auth-information')
        if $args->{auth} ne $config->{auth};
        
    # Clients can pass us HTML content or an URI where to fetch if
    if ( !defined $args->{html} ) {
        return $self->mkerror('no-html-nor-uri')
            if !$args->{uri};
        
        # Fetch the page
        my $ua = Mojo::UserAgent->new();
        my $tx = $ua->get($args->{uri});
        my $res = $tx->success;
        if (!$res) {
            my ($msg, $code) = $tx->error;
            return $self->mkerror("fetch-page-error: $msg");
        }
        $args->{html} = $res->body;
    }

    my $html_file = $self->make_html_file( $args->{html} );

    my $pdf_fn = $html_file->filename;
    $pdf_fn =~ s/\.html/.pdf/xms;

    # Build the command line
    my $hcmd = $self->build_wkh_command($args);
    $hcmd .= ' ' . $html_file->filename . " $pdf_fn";

    # Create the PDF file
    my $output = `$hcmd`; # TODO: error handling

    # Read the output and return it
    my $pdf_file = Path::Class::File->new($pdf_fn);
    my $pdf = $pdf_file->slurp();

    # Unlink the PDF file
    $pdf_file->remove();

    return $self->render_json({
        status  => 'ok',
        pdf     => encode_base64($pdf),
    });
};

helper build_wkh_command => sub {
    my ($self, $args) = @_;

    # Usual page size A4, but labels would need a smaller one so we leave it
    my $page_size = '--page-size ' . ($args->{page_size} || 'a4');

    # Custom page size will override the previous
    if ( defined $args->{page_width} && defined $args->{page_height} ) {
        $page_size = "--page-width $args->{page_width}"
            . " --page-height $args->{page_height} ";
    }

    # Build htmldoc command line
    my $hcmd = $config->{wkh} ." --encoding \"utf-8\" $page_size ";
    $hcmd .= "--margin-top $args->{top_margin}mm "
        if defined $args->{top_margin};
    $hcmd .= "--margin-left $args->{left_margin}mm "
        if defined $args->{left_margin};
    $hcmd .= "--margin-bottom $args->{bottom_margin}mm "
        if defined $args->{bottom_margin};
    $hcmd .= "--margin-right $args->{right_margin}mm "
        if defined $args->{right_margin};
    $hcmd .= "--orientation $args->{orientation} "
        if defined $args->{orientation};

    return $hcmd;
};

helper make_html_file => sub {
    my ($self, $html) = @_;

    my $htmlf = File::Temp->new(
        DIR     => $config->{tmpdir},
        SUFFIX  => '.html',
        UNLINK  => 1,
    );
    binmode $htmlf, ':encoding(UTF-8)';
    print $htmlf $html;

    return $htmlf; 
};

helper mkerror => sub {
    my ($self, $error) = @_;
    
    return $self->render_json({
        status  => 'error',
        error   => $error,
    });
};

app->start;

Once you have this setup (via CGI, FastCGI, morbo, starman or whatever you like best), you just need to POST you data via JSON, and it could be something like:

{
    "auth"    : "maitai",
    "html"    : "<html><head><meta charset=UTF-8></head><body>Ciao!</body></html>"
}

or:

{
    "auth"    : "maitai",
    "uri"     : "http://www.skm.to/"
}

and you get a JSON response such as this:

{
    "status"  : "ok",
    "pdf"     : "pdf_data_base64_encoded"
}

The PDF data is base64 encoded in order to be safely transferred without risking corruption because of character set encoding/decoding.

Some notes:

  • There are some configuration options (page size, ...): take a look at the source code.
  • Not all wkhtmltopdf features are implemented, but it's very easy to extend the software.
  • Authentication system is just an example, it should be way more robust.
  • Arguments should really be checked for safety, otherwise security issues could arise (well, provided the authentication system is broken before).
  • Error handling should be improved.

Why did I do this? Basically, I have some web apps hosted under a managed FreeBSD server, where compiling wkhtmltopdf does not work very well (and there are a lot of pre-requisites, anyway). This way I can "outsource" PDF generation easily.

Nasce Udine Programmers

| | Comments (0)

È nato Udine Programmers, un'idea che si propone di diventare un punto d'incontro per i programmatori (e le figure "collegate" come sistemisti, web designer, ...) di Udine e del Friuli.

Questo è l'attuale breve manifesto:

Studi o lavori su qualcosa che ha a che fare con la programmazione?
Vuoi conoscere altri programmatori?
Hai un progetto e cerchi collaboratori?
Cerchi lavoro come programmatore?
Ti servono consigli relativi alla programmazione?

Sull'esempio del Programmers in Padua, l'idea è quella di creare un punto di incontro per persone che si occupino di programmazione e attività correlate, in Friuli.

Tra gli scopi dell'iniziativa: permettere a persone che fan lavori simili di conoscersi (e quindi anche di scambiarsi possibilità di lavoro), organizzare meeting tecnici, cenare qualche volta assieme.

Professionisti, appassionati, studenti sono i benvenuti, come chiunque altro!

Ti aspettiamo!!!

http://www.udineprogrammers.it/

Beh... eccomi qua con qualche riga sull'Open Source Day 2011. Nel globale, gran manifestazione - con 3 tracce contemporanee ed una partecipazione direi abbondante di persone. Purtroppo ho seguito poco del convegno, poiché gestivo il tavolo dell'associazione Perl.It. Ho però dato un'occhiata qua e la e non sembravano mancare talk interessanti. Molto appropriata l'idea degli speed talk: uno spazio in corridoio dove chiunque poteva cimentarsi parlando in breve di qualcosa - ideale per chi vuol fare un intervento breve oppure non è abituato a parlare di fronte ad una platea e magari vuole iniziare in maniera più "morbida".

C'era l'immancabile Install Fest, dove in pratica uno porta il proprio PC su cui vuole installare Linux o un altro sistema operativo open source e può ottenere assistenza nell'installazione ed informazioni sull'utilizzo del sistema. L'Install Fest è sempre una parte importante ed utile in queste manifestazioni. Il Game Corner sembrava particolarmente interessante, nel senso che tutti si divertivano. Purtroppo durante il giorno non ho avuto granché tempo di cimentarmi e verso sera ormai era tardi per battersi in maniera competitiva con chi ormai aveva preso confidenza dalla mattina con le sparatorie - quindi mi sono limitato a dare un'occhiata.

Una bella iniziativa, che non ho visto in altre conferenze di questo tipo, era l'Area Bimbi. Il nome parla da sé: mentre segui le conferenze puoi lasciare i pargoletti nelle mani dell'eccellente staff dell'Open Source Day, che provvederà a fargli passare il tempo divertendosi. Fantastica idea!

Il pranzo self-service costava appena 10 Euro (OK, non ho pagato in quanto speaker in realtà) ed era piuttosto buono ed abbondante. Anche il bar interno all'Università era sempre aperto e a disposizione dei partecipanti.

Per quanto ho potuto vedere l'evento è filato via liscio come l'olio, e lo staff della reception - sempre molto disponibile - ha svolto un ottimo lavoro nel fornire supporto ai partecipanti (mi ci sono rivolto 2-3 volte, e per questioni non banali).

L'unico (piccolissimo) appunto che faccio per una manifestazione comunque riuscita alla grande è relativo alla mancanza di un evento serale: sarebbe bello ci fosse una cena "sociale" programmata (a cui uno si pre-iscrive, oppure paga il giorno stesso se ci sono ancora posti), sono sicuro non mancherebbero spunti per varie discussioni tecniche e non, per fare amicizia, e (perché no) per tirare tardi in giro per Udine.

Presentazion 0.60 is out, with some changes and many important bugfixes and optimizations.

Here's the change log:

Version 0.60 - 2011-11-18
    - Calculation of font size is now much more precise
    - Padding settings now moved to CSS file, so they can be
        * customized without changing the JS file
        * be different from screen to PDF/print version
    - Fixed ULs and OLs so list markers are inside the div and
      there's no risk of them crossing boundaries
    - Some code refactoring/optimization
    - Allow comments in multislides (lines beginning with //
      are ignored). Took the idea from a fork by stevan, but
      implemented it differently.
    - Fixed a bug which didn't allow to have multiple
      multislides in one presentation (thanks stevan)

See the original blog post for download and other information.

ZIP/Tarballs: download
github: project page

Every time I have to make a presentation, I'm always a bit confused about which software I should use to create and to show my slides, as no one seems to fit my needs (which are very simple, in fact).

Basically, what I want is:

  • Use a web browser to display slides, and be cross-browser at least with latest versions
  • Use a single HTML file to enter the slides data, avoiding at all applications like Impress or PowerPoint, which require a lot of time to create and move things around
  • Scale and display well on any resolution
  • Everything should be centred, both horizontally and vertically, and enlarged as much as possible
  • Center source code and left-align it
  • Painless PDF export

Surprisingly enough, all software out there misses at least a couple of these points: there are excellent tools for web browsers which provide a lot (too many?) features to make all kind of slides, but some don't seem to be able to centre and enlarge text automatically, others work only on a single vendor's browser. Moreover, nearly all of them lack an easy way to get a PDF copy of the slides, which is very important (when everything fails, a PDF displayed on a computer you borrow can save your presentation).

Enter Presentazion (the name is Friulian language for presentation).

Creating the slides is very simple, as they're all in the main file (the whole software consists of 4 small files). The recommended way to create slides is by using the multislide feature:

all lonesome lines are wrapped in p tags ---- and code... is automatically formatted as it should when leaving 4 blanks at the beginning of the line ---- unordered list // comments are ignored * one * two * three ---- ordered list # one # two # three ----

HTML is still ok to use

If you want full control over what you create, you can also directly create the slide DIVs - it's easy (even though a bit more verbose than the above example):

It's Friulian for presentation

Design Goals

  • Everything centered
  • ....

Code example

sub where_are_you { my $self = shift; say "I am in " . $self->place; }

slide and multislide can be combined (multiple times) in the same slidewhow at your convenience.

Now open the software in any recent web browser (yes, also Explorer is supported if you have at least version 8.0) and it will look like this example.

You can navigate with PgUp, PgDown and other keys - press h from within the presentation to see them all. You can also jump to a specific slide (press j), see where you are (press n) and even jump forward to a slide which contains a search pattern (press s).

Look can be customized by editing the CSS file.

And... PDF export works out of the box by using the excellent wkhtmltopdf piece of software: the PDF will be almost identical to the presentation you see on the web browser. Take a look at the example script to see how it works; there's also a print CSS which can be tweaked to change resolution, etc.

ZIP archives and tarballs of latest version can be downloaded by clicking here.

All code, which is released open source under the Artistic (perl5) or GPL v3 license, can be found in the Presentazion github repository.

Find recent content on the main index or look in the archives to find all content.

Recent Assets

  • thunderbird_logo.png

Categories

Pages

Powered by Movable Type 4.23-en