📜 ⬆️ ⬇️

Another way to generate PDF

Where can it come in handy? If it is necessary to generate print-ready files in a web application using an arbitrary rigid template that already exists: certificates, badges, passes and so on.

Why pdf? PDF format allows you to create documents with a number of undeniable advantages: openness, cross-platform, prevalence and, very importantly, the accuracy and invariance of data transmission along the chain of creation, viewing and printing.

What is the salt? In the use of SVG files as templates with the ability to substitute the necessary fields and then converted to PDF.
')
What are the benefits? The ability to create and quickly edit very complex patterns in familiar vector editors such as Adobe Illustrator, Corel Draw or Inkscape. Easy programming and using only free software. Another important advantage is the ability to transparently use UTF-8 for inserted texts.

What is needed for that? To use this method, you need a dedicated server with the ability to install your applications ( Inkscape and GhostScript ) and execute system commands. At the same time, everything will work on both the Windows platform and Linux.

I think a short FAQ highlighted the main issues on this method, so we will immediately proceed to the analysis of its essence.

As you know, the SVG vector graphics format is actually an XML file, so the file already created is quite simple to edit with the simplest programming tools. In the case of using the SVG file as a hard template, the process is simplified by several times, because we do not need to change the structure of the document, we just need to make the substitution of the necessary text values ​​or raster images encoded in base64.

You can create the initial template in any vector editor that supports export to svg: Adobe Illustrator, Corel Draw or in Inkscape itself. The use of the latter is desirable, at least at the last, final stage, since, ultimately, it is precisely him who will have to carry out the transformation we need.

When using a raster in a template, you can use 2 methods, store the raster in a separate external file or embedded in the SVG file itself. If you need to change the raster pattern in the template in the first case, you can also change the file before generation. When storing a picture embedded in a file, the following property should be entered in the URL property of the picture object:
Data:image/png;base64,{IMAGE}

where {IMAGE} is the field for inserting the encoded image using the base64 template engine.
Data: image / png; base64, {IMAGE}
For example, let's draw a simple badge template, I think you will forgive me for being crooked, I'm not an artist, but for real use, you can order a vector layout from your designer.
Badge template
I did not use a variable bitmap, leaving it for homework, and limited to only changeable text fields.

I think you have already noticed that template tags are inserted in the places of the intended text (in this example, FastTemplate was used). It is the use of XML compatible tags that makes it possible to register them in the vector editor itself without resorting to additional editing.

We have a template, and without problems we will be able to insert the data we need, but how will we actually carry out the conversion? To do this, use the Inkscape command line interface:
# PDF-
inkscape [source_svg_file] -A [dest_pdf_file]

Using the key " -A " we immediately get a PDF file, but, unfortunately, the created PDF directly has a very large size. To solve this problem you can go around. Namely, to use SVG export not directly in PDF, but in the SVG-> PS-> PDF chain. Using the ps2pdf utility from the Ghost Script suite to finalize the PDF file, we can reduce the size of the final file tenfold.
# PostScript-
inkscape [source_svg_file] -P [dest__ps_file]
# PostScript- PDF
ps2pdf [dest_ps_file] [dest_pdf_file]

The only drawback is that in this case we will lose all transparency effects, since the PostScript format does not support it.

For complete portability of the generated documents, you can add the Inscape option “ -T ” to convert all text into curves. This way we can get rid of the problems with the presence of fonts on the client machine, as well as problems with encodings.

Now we have everything we need: SVG template and transformation commands. Let's write a php script that would generate a pdf file generated from a template.

<? php
/ * ************************************************ *****************************************
* Script for the formation of a pdf-file skip using sequential conversion
* template to svg file, after which it is converted to a PostScript file by Inkscape,
* and the latter is converted to pdf using the ps2pdf utility.
*
* Author: Shebastyuk V.V. aka JStingo
* ************************************************* **************************************** * /

/ * script parameters * /

// Path to the folder with temporary files
// (if not specified, the files will be stored in the system temporary folder)
$ tmp_dir = '' ;

// generate paths to temporary svg, ps and pdf files
$ tmp_svg_file = tempnam ( $ tmp_dir , "" );
$ tmp_ps_file = tempnam ( $ tmp_dir , "" );
$ tmp_pdf_file = tempnam ( $ tmp_dir , "" );

/ * FastTemplate template engine * /
include ( "include / cls_fast_template.php" );
$ tpl = new FastTemplate ( "templates" );

try {

/ * Block with the data obtained for the template * /
/ * ........................... * /
$ user_name = 'JStingo' ;
$ register_date = '28 / 09/2007 ' ;
/ * ........................... * /
/ * form the name of the resulting file in the form User_name.pdf * /

$ pdf_file_name = $ user_name . '.pdf' ;

/ * processing the template and getting the resulting file * /

$ tpl -> define (array ( 'svg' => "template.svg" ));
$ tpl -> assign (array ( 'USER_NAME' => $ user_name ,
'R_DATE' => $ register_date
))
$ tpl -> parse ( 'SVG' , 'svg' );

// save the resulting svg file
$ tpl -> FastWrite ( 'SVG' , $ tmp_svg_file );

// perform the svg-file conversion by means of inkscape'a into a ps-file
// Keys
// -T - used to convert text to curves (for normal font support)
// -P - indicates the need to convert to a PostScript file
system ( "inkscape -T $ tmp_svg_file -P $ tmp_ps_file" , $ success );

// in case of unsuccessful execution of the conversion, we form an exception
if ( $ success ! = 0 )
throw new Exception ( “Error generating ps-file.” );

// convert the ps file to pdf using the ps2pdf utility

// Keys
// -dUseFlateCompression = true - sets the use of compression
// -dPDFSETTINGS = / printer - sets optimization for printing
system ( "ps2pdf -dUseFlateCompression = true -dPDFSETTINGS = / printer $ tmp_ps_file $ tmp_pdf_file" , $ success );

// in case of unsuccessful execution of the conversion, we form an exception
if ( $ success ! = 0 )
throw new Exception ( "Error generating pdf-file." );

// heading that we will send a pdf-file
header ( 'Content-type: application / pdf' );

// It will be called as $ pdf_file_name
header ( 'Content-Disposition: attachment; filename = "' . $ pdf_file_name . '"' );

// transfer the generated file
readfile ( $ tmp_pdf_file );

// delete temporary files
@ unlink ( $ tmp_svg );
@ unlink ( $ tmp_ps_file );
@ unlink ( $ tmp_pdf_file );

} catch ( Exception $ e ) {
/ * If an error has occurred somewhere, then we report it * /
$ tpl -> define (array ( 'error' => "error.tpl" ));
$ tpl -> assign ( 'ERROR' , $ e -> getMessage ());

$ tpl -> parse ( 'ERROR' , 'error' );
$ tpl -> FastPrint ( 'ERROR' );
}
?>

I think it will not be difficult for everyone to rewrite the script in another programming language.
An example of a file generated by a script .

Template and working script (provided that Inkscape and GhostScript are installed).

Source: https://habr.com/ru/post/30013/


All Articles