In previous versions of PDFreactor, the service stored temporary documents either in a default
directory or in a directory supplied by the docTempDir
server parameter.
To better support file systems that are shared between multiple services, it now uses a flat
structure.
In the rare case where server admins access the temporary document storage directly, the approach
might need to be adjusted.
Alternatively, you can restore the previous behavior by using the docTempStructure
server parameter and supplying the value datetime
.
Note that the datetime
structure is not recommended for shared file systems as it can
lead to race conditions.
In earlier versions of PDFreactor, content inside columns of a multi-column element could not overflow its column, and thus not overlap the content of the next column. Instead it was clipped between the columns. This behavior has been updated to match the browser behavior and the latest CSS specifications, which means that such overflowing content is now allowed.
To restore the legacy behavior, the new proprietary property -ro-column-clip
has been introduced,
which has to be applied on the multi-column element:
.multi-column-element { -ro-column-clip: auto; }
The algorithm to determine the column count of a multi-column element has been updated to the
latest specifications. The main difference is that in the earlier version, setting values to both
column-count
and column-width
at the same time caused the column-count
value to be ignored.
With the new implementation, it acts a maximum for the column count.
To restore the behavior of the old algorithm for cases where both column-width
and column-count
have
been set, override the value of column-count
with auto
:
.multi-column-element { column-count: auto; }
PDFreactor 11.4 now supports the min-width
and max-width
properties on table root elements.
If these properties are present in existing documents it can lead to a different layout result.
In order to revert such changes the following styles can be used:
table { min-width: auto; max-width: none; }
In earlier versions of PDFreactor, Asset Package conversions would automatically block certain URL connections, such as connections to local HTTP addresses, and would allow connections to JARs which were in the class path. This behavior was confusing and had nothing to do with Asset Packages. So from PDFreactor 11.3 onwards, only file system access outside of the Asset Package structure is prohibited. If you still want to prohibit connections to local HTTP addresses or if you want to allow access to specific JARs or other files, use PDFreactor's security settings.
Having any DebugSettings
specified in the PDFreactor configuration no longer disables
error policies to make sure that the resulting document and the conversion process is altered
as little as possible.
The location of the The .NET Standard 2.0 API library pdfreactor.dll
file changed. It
is now located at clients/netstandard2/lib/PDFreactor.dll
instead of
clients/netstandard2/bin/PDFreactor.dll
in the PDFreactor installation package or
installation directory.
The deprecated legacy API in the package com.realobjects.pdfreactor.legacy
has been removed.
If you are still using the legacy API, refer to the New API migration guide section.
The creation of PDF bookmarks and links is now enabled by default.
To disable the creation of bookmarks and links, use the following new configuration properties:
disableBookmarks
disableLinks
config.setDisableBookmarks(true); config.setDisableLinks(true);
The following configuration properties have been deprecated and their functionality was moved to other properties:
addBookmarks
→ disableBookmarks
addLinks
→ disableLinks
baseURL
→ baseUrl
logger
→ loggers
To configure a CustomUrlStreamHandler
for all protocols, in PDFreactor 11, use an asterisk as
value for the handler's protocol
property.
Previously, you had to use an empty string, which
is now deprecated.
config.setCustomUrlStreamHandlers( new CustomUrlStreamHandler() .setProtocol("*")// empty string ("") is deprecated
.setHandler(new URLStreamHandler() {// your implementation
}) );
When exporting an empty string from JavaScript using the ro.exports
property, it is
now converted to null
when accessed through the Result
object in the
PDFreactor integration.
In previous versions, the PDFreactor Web Service Clients were known as Wrappers or Wrapper-APIs. They are now consistently named clients and their directories in the package have been renamed accordingly.
Also, various methods in the Clients did throw generic exceptions or errors. In PDFreactor 11, these exceptions and errors are now typed and can be explicitly handled in the integration code if so desired.
This does not affect the Java or .NET Clients, as they already threw typed exceptions in previous versions.
try { // ... } catch (e) { if (e instanceof PDFreactor.PDFreactorWebserviceError) { // Since 'e' is now an object, use 'e.message' to access the error message // ... } }
try { // ...} catch (Exception $e) {} catch (PDFreactorWebserviceException $e) { // ... }
try: # ...except Exception as e:except PDFreactorWebserviceException as e: # ... }
begin # ...rescue Exception => errorrescue PDFreactor::PDFreactorWebserviceError => error # ... }
eval { # ... } || do { if ($e->isa("PDFreactor::PDFreactorWebserviceException")) { # ... } }
In previous versions of PDFreactor, CSS selectors were generally case-insensitive. However, this has been changed in order to comply with the latest HTML 5 specifications.
For example, ID and class selectors are now case-sensitive. This means that if such selectors used incorrect casing, these will have to be adjusted or they will no longer be applied as intended.
When using an attribute selector to compare attribute values, this compare is now case-sensitive in certain cases,
depending on the attribute name. The selector can be modified with an i
, to make it case-insensitive again:
li[class^="a"] {/*...*/
}/* Matches class="a", but not class="A" */
li[class^="a" i] {/*...*/
}/* Matches both class="a" and class="A" */
PDFreactor now reads orientation data from images by default and rotates the images accordingly.
:root { -ro-image-orientation: none; }
Absolute positioning has been corrected, so when boxes are positioned against their page they are positioned against the pages content box instead of its padding box.
body > div.pos {
-ro-position-origin: padding-box;
position: absolute;
/* top: ...*/
}
The HTML list elements <ol>
, <ul>
and <dl>
no longer set 'break-before: avoid
'.
ol, ul, dl { break-before: avoid; }
The proprietary CSS media feature '-ro-output-format: pdf
' no longer matches when the document is viewed in the PDFreactor Preview application, only for
actual conversions to PDF. To specify styles that should apply in the Preview App, the new value viewer
has been introduced.
/* equals the old behavior of 'pdf' */
@media (-ro-output-format: pdf), (-ro-output-format: viewer) {/*...*/
}
CSS properties that accept integer values are now invalid if float numbers are used
instead. While in previous versions, a float was accepted as long as it was a
whole number (e.g. 'counter-increment: counter 1.0
' used to work), this is no
no longer the case.
The only way to restore the previous behavior is to disable CSS validation:
config.setCssSettings(new CssSettings().setValidationMode(CssPropertySupport.ALL));
PDFreactor now includes new proprietary CSS properties for detailed control over barcodes, deprecating the old functionality, which was based on XML. Legacy barcodes still work, but only if the correct namespace was set on the barcode element:
<barcode:barcode xmlns:barcode="http://barcode4j.krysalis.org/ns" message="123456789012"> <barcode:ean-13/> </barcode:barcode>
Also, please note that there is no separate barcode type for GS1-128/EAN128 barcodes. To create them, you
need to generate a Code128 barcode and set its encoding to gs1:
.gs1-128 { -ro-barcode-type: code128; -ro-barcode-encoding: gs1; }
More information on the new properties can be found in the manual.
PDFreactor 8 introduced a new Python-based command line interface (CLI) which replaced the old Java-based CLI. However, the Python CLI was dependent on the PDFreactor Web Service and had some inherent limitations.
PDFreactor 11 again includes a Java-based CLI that can be used without a service. Both this new CLI, as well as the Python one, now use a new API:
One major change is that you can only specify simple configuration properties directly (i.e. properties that take string, number, boolean or enum parameters). Complex properties have to be specified in a separate JSON file. This makes the API cleaner and easier to use. There are still shortcuts to add user style sheets and user scripts.
python pdfreactor.py -i in.html -o out.pdf -c style.css -C additionalConfig.json
java -jar pdfreactor.jar -i in.html -o out.pdf -c style.css -C additionalConfig.json
The pdfreactor.exe
file is now an executable for the new Java-based CLI, so integrators relying on
the PDFreactor Web Service may have to adjust their integration or use the Python-based CLI via the
pdfreactor.py
script.
Below is a quick overview of CLI-specific arguments. The list does not include configuration properties.
Please also refer to the documentation of the respective CLI, via the -h
parameter.
Arg | Description |
---|---|
-h | Help |
-i | Input document |
-o | Output document |
-c | Additional CSS (supports: content, file and URL) |
-j | Additional JavaScript (supports: content, file and URL) |
-x | Additional XSLT (supports: content, file and URL) |
-C | Additional configuration in JSON format |
-v | Verbose logging output |
-q | Quiet mode (no logging output) |
-d | Debug mode |
-I | Inspectable mode |
-V | Show version |
-N | Number of runs (Java only) |
-W | Number of warm-ups (Java only) |
-s | Server URL (Python only) |
-a | Treat input as Asset Package (Python only) |
PDFreactor now features configurable security behavior to prevent attacks in form of the injection of malicious code from potentially untrusted third parties that produce content which is converted by PDFreactor.
Because of the default security settings, there are some behavior changes:
Please refer to the PDFreactor manual for a detailed description of the security settings and the default behavior.
You can recreate the previous unsafe behavior by using the following security settings. This also works in the deprecated legacy API. Please note that this is strongly discouraged if you process content from potentially untrusted sources.
config.setSecuritySettings(new SecuritySettings() .setAllowExternalXmlParserResources(true) .setDefaults(new SecurityDefaults() .setAllowFileSystemAccess(true)));
PDFreactor Web Service users can configure the security settings via server parameters. Please refer to the manual for more information.
PDFreactor Web Service users: If you have customized the "start.ini" file of the Jetty server, please see section PDFreactor Web Service Jetty before installing PDFreactor 10.
The CSS Validator is now enabled by default. In PDFreactor 9 the validation was disabled, thus invalid values could overwrite valid ones. Now with the validation enabled, invalid values are completely ignored, as if they were not in the style rule.
To disable the Validator, use the API method setCssSettings
:
config.setCssSettings(new CssSettings().setValidationMode(CssPropertySupport.ALL));
The images that are produced when rasterizing SVGs and canvas elements have now a maximum size of 2 megapixels by default. If the image would be larger, the resolution is reduced. This way, the used memory and the size of the resulting PDF are reduced. The following snippet disables this limit:
svg, canvas, img, object, embed { -ro-rasterization-max-size: none; }
The property can also be used to increase the max-size to a certain megapixel value:
svg, canvas, img, object, embed { -ro-rasterization-max-size: 3.5; }
Rendering MathML now requires the import of a MathML library. We recommend MathJax, as it creates better results than the lib PDFreactor used in previous versions.
If the input document can not be modified, the following user scripts can be defined to include and use MathJax. The first script consists of settings for the next one:
Please see the comments in the snippet for example values:
roMjPath = ""; // default: "", // examples: "MathJax/", "../../resource/js/mathjax/", // "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/" roMjFile = "MathJax.js"; // default: "MathJax.js", // examples: "mathjax.js", "mathjaxmod.js" roMjSvgBlacker = 0; // default: 0, // examples: 1, 2
The second script uses the values form the first one and inserts the required script elements into the document, so MathJax is loaded and processes all "math" elements. It does not have to be modified.
document.documentElement.firstElementChild.insertAdjacentHTML('beforeend', '\u003Cscript type="text/x-mathjax-config">MathJax.Hub.Config(' + JSON.stringify({ jax: ["input/MathML", "output/SVG"], extensions: ["mml2jax.js"], MathML: { extensions: ["content-mathml.js"] }, SVG: { blacker: (typeof window.roMjSvgBlacker == "number" && window.roMjSvgBlacker > 0 ? window.roMjSvgBlacker : 0) } }) + ');\u003C/script>\n' + '\u003Cscript type="text/javascript" src="' + (window.roMjPath ? window.roMjPath : "MathJax/") + (window.roMjPath && !(window.roMjPath + "").endsWith("/") ? "/" : "") + (window.roMjFile ? window.roMjFile : "MathJax.js") + '">\u003C/script>' );
As defined by the CSS3 specifications, 'text-align' is now handled as a shorthand for 'text-align-all' and 'text-align-last'. This means that, if 'text-align-last' is defined before 'text-align', the last line alignment will be overridden.
This can be avoided by using 'text-align-all' instead of 'text-align'.
Furthermore 'text-align-last' now also works if the paragraph has not been set to 'justify'.
The default styles for several form fields was updated to a more modern look. Authors that rely on these default styles should verify their documents. If necessary, the legacy styles can be recreated using CSS.
When digitally signing a PDF using the signPDF
configuration property, PDFreactor will now throw an exception and thus
fail the conversion if the PDF could not be signed. Appropriate log entries as well as exception messages will provide
information as to the reason.
In previous versions, the "convert" methods were throwing various exceptions. In PDFreactor 10, this has bee reduced to only a single exception type—the
PDFreactorException
. Previously thrown exceptions are now wrapped in PDFreactorException
s and are available as their cause.
If you are trying to catch the older exception types in your integration, you will receive compile errors.
To resolve this, just remove the now superfluous catch blocks:
try { pdfReactor.convert(config); } catch (PDFreactorException e) { // ...} catch (IOException e) { // ... } catch (SAXException e) { // ... } catch (TransformerException e) { // ...}
When upgrading to PDFreactor 10 via one of the installers, an existing "start.ini" file will now always be overwritten. If you have made any changes to it, it is highly recommended that you backup these changes before installing PDFreactor 10. The installer will also do a backup of an existing "start.ini" file.
From PDFreactor 10 onward, any customizations of Jetty should no longer be done in the "start.ini" file but instead in the new "main.ini" and other "ini" files located in the "PDFreactor/jetty/start.d" directory.
The JavaScript client API was changed. Instead of using callback parameters, the API methods now return Promises.
PDFreactor 9− example:
pdfReactor.convert(config, function(result) { processResult(result); }, function(error) { processError(error); });
PDFreactor 10 example:
try { const result = await pdfReactor.convert(config); processResult(result); } catch (error) { processError(error); }
For more information, please refer to the new JavaScript integration examples and the JavaScript API documentation.
The class
com.realobjects.pdfreactor.webservice.client.Log.LogRecord
has been moved and renamed to
com.realobjects.pdfreactor.webservice.client.Record
All methods that returned lists now return arrays instead.
The namespace of the class
RealObjects.PDFreactor.Webservice.Client.Log.Record
has been changed to
RealObjects.PDFreactor.Webservice.Client.Record
The property
ExceedingContent
of the Result
class has been renamed to
ExceedingContents
The configuration properties appendLog
and enableDebugMode
are now obsolete. Use debugSettings
instead.
Old API | New API |
Enabling JavaScript | |
config.setJavaScriptMode(true); |
config.setJavaScriptSettings( new JavaScriptSettings().setEnabled(true)); |
Enabling debug mode | |
config.setEnableDebugMode(true); |
config.setDebugSettings( new DebugSettings().setAll(true)); |
Appending the log | |
config.setAppendLog(true); |
config.setDebugSettings( new DebugSettings().setAppendLogs(true)); |
Setting resource timeout | |
config.setResourceRequestTimeout( Integer); |
config.setResourceReadTimeout(Integer); config.setResourceConnectTimeout(Integer); |
Setting a color space | |
config.setDefaultColorSpace( ColorSpace); |
config.setColorSpaceSettings( new ColorSpaceSettings().setTargetColorSpace( ColorSpace)); |
The String-function takes 2 parameters, with the second being a keyword to specify which value should be used, if there are multiple assignments for that named string on a single page.
In accordance with the CSS specifications, the identifier last-except
has been renamed.
The keyword last-except
content: string(namedString, last-except);
has been replaced with first-except
content: string(namedString, first-except);
which has the same effect.
With PDFreactor 9 some of the standard HTML styles have been edited to be more in line with the HTML5 specification and modern browsers. While most changes are cosmetic, some will influence the layouts of existing documents. When these have a negative impact on existing documents and adapting the print styles accordingly is to complex, the following snippets can be used to undo the most significant changes:
The default page margins were increased from 1cm to 2cm.
@page { margin: 1cm; }
In previous versions of PDFreactor the default margins of body elements were 8px, in accordance to the HTML specification. As these default margins are only useful in non-paged environments they were dropped in PDFreactor 9.
body { margin: 8px; }
For this to take effect in multi-page documents the following snippet has to be applied as well.
The default value of the property box-decoration-break is now slice, as per the specification. The margin, padding and border-width values around page break will be treated as 0.
* { box-decoration-break: clone; }
The default value of the proprietary property -ro-rounding-mode is now floor. This avoids rare cases where accumulated rounding imprecisions could lead to unexpected layout results, but may lead to different line and page-breaks.
html { -ro-rounding-mode: round; }
The default side of first pages has changed from left to recto (i.e. right, unless the document direction is right-to-left), as per the specification.
@-ro-preferences { first-page-side: left; }
The top margins of blocks at the start of pages and columns are no longer set to 0 for first pages and columns or after forced breaks. This matches the behavior of browsers and the requirements of the latest CSS specifications.
html { -ro-truncate-margin-after-break: always; }
However, in most cases it is advisable to apply non-proprietary styles, that result in the same improvement in browsers.
h1 { break-before: page; margin-top: 0; } div.multiColumn > *:first-child { margin-top: 0; }
The package of the ExceedingContent
class has been changed from
com.realobjects.pdfreactor.exceedingcontent
to
com.realobjects.pdfreactor.contentobserver
The method setDocument(Object)
is obsolete, use setDocument(String)
,
setDocument(byte[])
or setDocument(InputSource)
instead. This only affects
the non-client Java library.
Constructors of inner Configuration
classes (except for the KeyValuePair
class) that take multiple arguments
have been deprecated and will be removed in a future version. Use the no-argument
constructor in conjunction with individual setters
instead. An exception is the KeyValuePair
class whose multi-argument constructor is not deprecated.
Setters now return an instance of the class, thus allowing you to chain
multiple subsequent setter calls. The following example demonstrates using no-argument constructors
and chainable setters by adding a user script and a user style sheet to a Configuration
instance:
config.setAttachments(new Attachment(null, "http://myAttachment.zip", null, null)); config.setUserStyleSheets(new Resource("p { color: red; }", null));
config .setAttachments(new Attachment().setUri("http://myAttachment.zip")); .setUserStyleSheets(new Resource().setContent("p { color: red; }"));
Multi-argument constructors are now obsolete in favor of object initializers.
config.Attachments.Add(new Attachment(null, "http://myAttachment.zip", null, null)); config.UserStyleSheets.Add(new Resource("p { color: red; }", null));
config.Attachments.Add(new Attachment { Uri = "http://myAttachment.zip" }); config.UserStyleSheets.Add(new Resource { Content = "p { color: red; }" });
The PDFreactor PHP classes are now located in the namespace
com\realobjects\pdfreactor\webservice\client\
. To adjust your integration,
just add appropriate use
directives like this:
use com\realobjects\pdfreactor\webservice\client\PDFreactor as PDFreactor; use com\realobjects\pdfreactor\webservice\client\LogLevel as LogLevel; use com\realobjects\pdfreactor\webservice\client\ViewerPreferences as ViewerPreferences; ...
The configuration properties mergeByteArray
, mergeByteArrays
,
mergeURL
and mergeURLs
are now obsolete. Use
mergeDocuments
instead. Note that mergeDocuments
takes
one or more Resource
objects,
so you have to use the appropriate properties of that object, either
data
for binary data or uri
for URLs. Java example:
// merge single document from binary source config.setMergeByteArray(byteArray1); // merge multiple documents from binary source config.setMergeByteArrays(byteArray1, byteArray2); // merge single document from URL source config.setMergeByteURL(url1); // merge multiple documents from URL source config.setMergeByteURLs(url1, url2);
// merge single document from binary source config.setMergeDocuments(new Resource().setData(byteArray1)); // merge multiple documents from binary source config.setMergeDocuments(new Resource().setData(byteArray1), new Resource().setData(binary2)); // merge single document from URL source config.setMergeDocuments(new Resource().setUri(url1)); // merge multiple documents from URL source config.setMergeDocuments(new Resource().setUri(url1), new Resource().setUri(url2)));
The ScriptResource
type is now deprecated, use Resource
instead.
This change only affects Java and .NET APIs.
When using either the Java or .NET Clients, your integration has to be adjusted. These clients are now based on the REST API rather than the SOAP API. This was done to provide an API that is more in line with the other clients.
When using the PDFreactor Web Service with custom settings in the "pdfreactorwebservice.vmoptions" file, you have to migrate these settings to the "start.ini" located in the "PDFreactor/jetty" directory.
If your "pdfreactorwebservice.vmoptions" looked like this
-Xmx1024m -Djava.awt.headless=true
you have to add the lines from your "pdfreactorwebservice.vmoptions" to the end of your "start.ini" file
--exec -Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Slf4jLogger -Dcom.realobjects.interceptConsoleOutput=true # old pdfreactorwebservice.vmoptions settings -Djava.awt.headless=true -Xmx1024m
With PDFreactor 8 we are introducing the first major API change since PDFreactor 2. One major benefit of this change is that the new Java API is identical (with a few additions) to the newly introduced Java web service client API.
Java integrators can still use the old API, however we highly recommend to migrate to the new API as soon as possible, since the old one will be removed in a future release of PDFreactor. To continue using the old legacy API, just change the package from
com.realobjects.pdfreactor
to
com.realobjects.pdfreactor.legacy
The most obvious change is the introduction of the Configuration
object. In previous versions of PDFreactor,
you invoked all API methods on the PDFreactor instance, however this had some disadvantages like making the
PDFreactor instance non-reusable. In PDFreactor 8, you just have to create one instance of PDFreactor. The instance
only has a few API methods, like convert
.
All settings and options are properties of the configuration and have to be set there. While most methods are the same as in previous versions of PDFreactor, some have changed. For example, instead of add-methods, getters are used to retrieve lists on which new entries can be added. Make sure to consult the API documentation.
To create a PDF or image, you now just have to call the convert
method with the configuration as a
single parameter, which also specifies the input document.
PDFreactor automatically detects if you are converting an HTML string, a URL or binary data.
The new convert(Configuration)
method no longer returns the PDF as binary directly. It returns a Result
object which not only contains the PDF as binary, but also other useful data such as the log.
There are additional convert methods, such as convert(Configuration, OutputStream)
which writes
the PDF directly in the specified OutputStream instead of returning it or convertAsBinary(Configuration)
which returns the binary data directly instead of a Result object. Please make sure to read the API documentation and
the PDFreactor manual (Chapter "Integration").
Below are simple examples in different programming languages that show how PDFreactor was used previously and how it is used now.
PDFreactor pdfReactor = new PDFreactor(); // simple settings pdfReactor.setAddBookmarks(true); pdfReactor.setAddLinks(true); // adding a user style sheet pdfReactor.addUserStyleSheet("p { color: red }", null, null, null); // create PDF and specify the document byte[] pdf = pdfReactor.renderDocumentFromURL("https://www.realobjects.com");
PDFreactor pdfReactor = new PDFreactor(); Configuration config = new Configuration(); // specify the document config.setDocument("https://www.realobjects.com"); // simple settings config.setAddBookmarks(true); config.setAddLinks(true); // adding a user style sheet config.getUserStyleSheets().add(new Resource("p { color: red }", null)); // create PDF Result result = pdfReactor.convert(config); byte[] pdf = result.getDocument();
PDFreactor pdfReactor = new PDFreactor(); // simple settings pdfReactor.SetAddBookmarks(true); pdfReactor.SetAddLinks(true); // adding a user style sheet pdfReactor.AddUserStyleSheet("p { color: red }", "", "", ""); // create PDF and specify the document byte[] pdf = pdfReactor.RenderDocumentFromURL("https://www.realobjects.com");
PDFreactor pdfReactor = new PDFreactor(); Configuration config = Configuration(); // specify the document config.Document = "https://www.realobjects.com"; // simple settings config.AddBookmarks = true; config.AddLinks = true; // adding a user style sheet config.UserStyleSheets = new List<Resource> {new Resource("p { color: red }", "")}; // create PDF Result result = pdfReactor.Convert(config); byte[] pdf = result.Document;
$pdfReactor = new PDFreactor(); // simple settings $pdfReactor->setAddBookmarks(true); $pdfReactor->setAddLinks(true); // adding a user style sheet $pdfReactor->addUserStyleSheet("p { color: red }", "", "", ""); // create PDF and specify the document $result = $pdfReactor->renderDocumentFromURL("https://www.realobjects.com");
$pdfReactor = new PDFreactor(); $config = array( // specify the document "document" => "https://www.realobjects.com", // simple settings "addBookmarks" => true, "addLinks" => true, // adding a user style sheet "userStyleSheets" => array( array( "content"=> "p { color: red }" ) ) ); // create PDF // ...as base64 encoded String $result = $pdfReactor->convert($config); $pdf = $result->document; // ...as binary $pdf = $pdfReactor->convertAsBinary($config);
To convert the base64 encoded document into binary data, you can do the following:
echo base64_decode($result->document);
pdfReactor = PDFreactor() # simple settings pdfReactor.setAddBookmarks(True) pdfReactor.setAddLinks(True) # adding a user style sheet pdfReactor.addUserStyleSheet("p { color: red }", "", "", "") # create PDF and specify the document result = pdfReactor.renderDocumentFromURL("https://www.realobjects.com");
pdfReactor = PDFreactor() config = { # specify the document 'document': "https://www.realobjects.com", # simple settings 'addBookmarks': True, 'addLinks': True, # adding a user style sheet 'userStyleSheets': [ { 'content': "p { color: red }" } ] } # create PDF # ...as base64 encoded String result = pdfReactor.convert(config) pdf = result['document'] # ...as binary pdf = pdfReactor.convertAsBinary(config)
To convert the base64 encoded document into binary data, you can do the following:
import base64 print(base64.b64decode(result['document']))
pdfReactor = PDFreactor.new(); # simple settings pdfReactor.setAddBookmarks(true) pdfReactor.setAddLinks(true) # adding a user style sheet pdfReactor.addUserStyleSheet("p { color: red }", "", "", "") # create PDF and specify the document result = pdfReactor.renderDocumentFromURL("https://www.realobjects.com")
pdfReactor = PDFreactor.new() config = { # specify the document document: "https://www.realobjects.com", # simple settings addBookmarks: true, addLinks: true, # adding a user style sheet userStyleSheets: [ { content: "p { color: red }" } ] } # create PDF # ...as base64 encoded String result = pdfReactor.convert(config) pdf = result["document"] # ...as binary pdf = pdfReactor.convertAsBinary(config)
To convert the base64 encoded document into binary data, you can do the following:
require "base64" print Base64.decode64(result["document"])
my $pdfReactor = PDFreactor -> new(); # simple settings $pdfReactor -> setAddBookmarks('true'); $pdfReactor -> setAddLinks('true'); # adding a user style sheet $pdfReactor -> addUserStyleSheet("p { color: red }", "", "", ""); # create PDF and specify the document $result = pdfReactor -> renderDocumentFromURL("https://www.realobjects.com");
my $pdfReactor = PDFreactor -> new(); $config = { # specify the document 'document' => "https://www.realobjects.com", # simple settings 'addBookmarks' => 'true', 'addLinks' => 'true', # adding a user style sheet 'userStyleSheets' => [ { 'content' => "p { color: red }" } ] }; # create PDF # ...as base64 encoded String $result = $pdfReactor -> convert($config); $pdf = $result->{'document'}; # ...as binary $pdf = $pdfReactor -> convertAsBinary($config);
To convert the base64 encoded document into binary data, you can do the following:
use MIME::Base64 (); print MIME::Base64::decode($result->{'document'});