Technical FAQs

Question

In PrizmDoc, my text annotation won’t fit the bounding box as if there is padding on the text. How can I fix this?

Answer

Check to see if there’s any custom styling to the body tags. If you have any sort of padding applied to the "body" element in the CSS, it may affect the text annotation, which is a foreign object with a body tag in it.

Question

What is the absolute bare minimum I need to use PrizmDoc Cloud?

Answer

This will allow you to load a document via a URL using PrizmDoc Cloud. Just include your PrizmDoc Cloud API key in the POST request headers.

Please note: This is purely intended as a proof-of-concept. You should never include your API key in your client-side Javascript.

<!DOCTYPE html>

<html lang="en">
<head>
    <!-- Metadata -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="description" content="" />

    <!-- Title -->
    <title>AccuSample</title>

    <!-- Libraries -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css">

    <!-- PrizmDoc CSS -->
    <link rel="stylesheet" href="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/css/viewercontrol.css">
    <link rel="stylesheet" href="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/css/viewer.css">

    <!-- Inline Stylesheet -->
    <style></style>

</head>
<body>

    <!-- #viewer -->
    <div id="viewer" class="pccv pcc-full-screen"></div>

    <!-- Libraries -->
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/jquery-3.4.1.min.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/jquery.hotkeys.min.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/underscore.min.js"></script>

    <!-- PrizmDoc JS -->
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/viewercontrol.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/viewer.js"></script>
    <script src="https://raw.githack.com/Accusoft/hello-prizmdoc-viewer-with-nodejs-and-html/master/public/viewer-assets/js/viewerCustomizations.js"></script>

    <!-- Inline Script -->
    <script>

        let viewingSessionId;
        let viewerControl;

        $(document).ready(function() {
            $.ajax({
                "type": "POST",
                "url": "https://api.accusoft.com/prizmdoc/ViewingSession",
                "headers": {
                    "acs-api-key": "4lTamQVZmrkqZhH8cZhdu7L0xyhUa3gorcaCFQpA_zmuowZs4zoF39V4IckpnVW_"
                },
                "data": JSON.stringify({
                    "source": {
                        "type": "url",
                        "url": "https://www.usability.gov/sites/default/files/creating-wireframes.pdf"
                    }
                })
            }).done(function(response) {
                PCCViewer.Ajax.setHeaders({
                    "acs-api-key": "4lTamQVZmrkqZhH8cZhdu7L0xyhUa3gorcaCFQpA_zmuowZs4zoF39V4IckpnVW_"
                });

                viewingSessionId = response["viewingSessionId"];

                // Initialize viewer
                viewerControl = $("#viewer").pccViewer({ 
                    "documentID": viewingSessionId,
                    "imageHandlerUrl": "https://api.accusoft.com/prizmdoc",
                    "language": viewerCustomizations.languages["en-US"],
                    "template": viewerCustomizations.template,
                    "icons": viewerCustomizations.icons,
                    "annotationsMode": "LayeredAnnotations"
                }).viewerControl;

                viewerControl.on("ViewerReady", function() {
                    console.log("Ready!");
                });
            });
        });

    </script>

</body>
</html>
Question

Can I host multiple PrizmDoc viewers on a single page?

Answer

It is possible to host multiple viewers on a single page. The following example leverages Bootstrap’s tab implementation:

<!DOCTYPE html>

<html lang="en">
<head>
    <!-- Metadata -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
    <meta name="description" content="" />

    <!-- Title -->
    <title>AccuSample</title>

    <!-- Libraries -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css">

    <!-- PrizmCSS -->
    <link rel="stylesheet" href="https://pcc-demos.accusoft.com/static/viewer-latest/css/viewercontrol.css">
    <link rel="stylesheet" href="https://pcc-demos.accusoft.com/static/viewer-latest/css/viewer.css">

    <!-- Inline Stylesheet -->
    <style>
        body {
            overflow-y: hidden;
        }
        #viewer1, #viewer2 {
            height: calc(100vh - 3em);
            width: 100%;
        }
    </style>

</head>
<body>
    <!-- #main -->
    <main class="container">
        <ul class="nav nav-tabs" role="tablist">
            <li class="nav-item">
                <a class="nav-link active" id="viewer1-tab" data-toggle="tab" href="#viewer1">Viewer 1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" id="viewer2-tab" data-toggle="tab" href="#viewer2">Viewer 2</a>
            </li>
        </ul>

        <div class="tab-content">
            <div class="tab-pane fade show active" id="viewer1" role="tabpanel">
                <div id="viewer1">
                </div>
            </div>
            <div class="tab-pane fade" id="viewer2" role="tabpanel">
                <div id="viewer2">
                </div>
            </div>
        </div>
    </main>

    <!-- Libraries -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.1/umd/popper.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

    <!-- PrizmJS -->
    <script src="https://api.accusoft.com/v1/docstore/viewer/assets/classic/bundle.js"></script>
    <script src="https://pcc-demos.accusoft.com/static/viewer-latest/js/jquery.hotkeys.min.js"></script>
    <script src="https://pcc-demos.accusoft.com/static/viewer-latest/js/viewercontrol.js"></script>
    <script src="https://pcc-demos.accusoft.com/static/viewer-latest/js/viewer.js"></script>

    <!-- Inline Script -->
    <script>
        var viewingSessionId1;
        var viewerControl1;
        var viewingSessionId2;
        var viewerControl2;

        $(document).ready(function() {
            $.ajax({
                "type": "post",
                "url": "https://api.accusoft.com/PAS/V1/ViewingSession",
                "headers": {
                    "acs-api-key": ""
                },
                "data": JSON.stringify({
                    "source": {
                        "type": "url",
                        "url": ""
                    }
                })
            }).done(function(response) {
                viewingSessionId1 = response["viewingSessionId"];

                // Initialize viewer
                viewerControl1 = $("#viewer1").pccViewer({ 
                    documentID: viewingSessionId1,
                    imageHandlerUrl: "https://api.accusoft.com/v2/viewers/proxy",
                    language: languageItems,
                    template: htmlTemplates
                }).viewerControl;
            });

            $.ajax({
                "type": "post",
                "url": "https://api.accusoft.com/PAS/V1/ViewingSession",
                "headers": {
                    "acs-api-key": ""
                },
                "data": JSON.stringify({
                    "source": {
                        "type": "url",
                        "url": ""
                    }
                })
            }).done(function(response) {
                viewingSessionId2 = response["viewingSessionId"];

                // Initialize viewer
                viewerControl2 = $("#viewer2").pccViewer({ 
                    documentID: viewingSessionId2,
                    imageHandlerUrl: "https://api.accusoft.com/v2/viewers/proxy",
                    language: languageItems,
                    template: htmlTemplates
                }).viewerControl;
            });
        });
    </script>
</body>
</html>
Question

When viewing documents within the PrizmDoc Viewer using a particular browser, we are seeing garbage text. Viewing the same document with other browsers shows the text properly. What could be causing this to occur?

Answer

There are two possible causes for this in Internet Explorer 11 and you can check the settings below to potentially fix the issue:

In Internet Explorer 11 settings, ensure the Font Download option is enabled:

  1. Click on Internet Options.
  2. Select the Security Tab.
  3. Under Local Intranet zone, select Custom Level.
  4. Under Downloads, set Font download to Enabled.

Disable the “Turn off Data URI” support setting:

  1. Click Start, type gpedit.msc in the Start Search box, and then press Enter.
  2. In the navigation pane of the Local Group Policy Editor window, expand Computer Configuration > Administrative Templates > Windows Components > Internet Explorer > Security Features.
  3. In the right pane, double-click Turn Off Data URI support.
  4. Select Disable, click Apply, and then click OK.
  5. Go back to the navigation pane of the Local Group Policy Editor window, expand User Configuration > Administrative Templates > Windows Components > Internet Explorer > Security Features.
  6. Repeat steps 3 and step 4 above.

In Internet Explorer 11 settings, ensure Ignore font styles specified in webpages is not checked.

  1. Click on Internet Options.
  2. Select the General Tab.
  3. Click on Accessibility button.
  4. Un-check Ignore font styles specified in webpages.

In Chrome this is a bug that was found about 3 years ago and fixed in Chrome Canary, but not in Chrome Stable at the time:

https://productforums.google.com/forum/#!msg/chrome/rpmz56gnFKc/nPLtsbYZBwAJ

This may be why Chrome is having problems. Consider either updating Chrome Stable to the latest version or testing in Chrome Canary to see if that fixes the garbage character issues with that browser.


In Mozilla Firefox there is a setting you can enable which could resolve this problem in that browser:

  1. Go to Options/Preferences > General: Fonts & Colors > Advanced and select Allow pages to choose their own fonts (instead of My selections above).
Question

When running PrizmDoc on multiple servers using self-hosted cloud licensing, why is the service randomly stopping on one server but not another?

Answer

When using cloud licenses, we require that the server running PrizmDoc has internet access. The server needs to communicate with the Amazon S3 bucket used for the license, and also to verify you are within the CPU core count you are licensed for.

If you are seeing the Prizm service stop on certain systems with this type of
license, you can verify the following:

  1. For all servers using this license, verify the core count on each server and then add them up. If the total number of cores exceeds what you are licensed for, then the Prizm service will shut down on the server where the service was started first after it checks the S3 bucket and determines the core count has been exceeded.
  2. If the server’s DNS resolution becomes unstable and the server is unable to resolve URLs, the Prizm service on that server will be unable to verify the license on the S3 bucket, which will cause the Prizm service to stop.
  3. Verify that the server has the appropriate rights to the S3 bucket outlined in the following FAQ: What specific rights are required on an AWS S3 bucket for PrizmDoc Cloud licensing to work?
Question

With PrizmDoc, how can I hide a predefined search if there are no results?

Answer

The predefined search option does not support that functionality, but you can instead perform a server-side search, and then activate the search panel if there are results to show:

var viewer;
var viewingSessionId = <%= viewingSessionId %>;

var fixedSearchTerm = "the";
var pasUrl = "/pas";

var viewerReady = false;
var searchReady = false;
var searchDisplayed = false;

function displaySearchIfNeeded() {
    // The search is only displayed once the viewer is ready, and once our preliminary server-side search comes back positive.
    if (viewerReady && searchReady && !searchDisplayed) {
        searchDisplayed = true;

        $("[data-pcc-search=\"input\"]").val(fixedSearchTerm);
        $("[data-pcc-search=\"submit\"]").click();
    }
}

function sendSearchPost() {
    $.ajax({
        "method": "POST",
        "url": pasUrl + "/v2/viewingSessions/" + viewingSessionId + "/searchTasks",
        "data": JSON.stringify({
            "input": {
                "searchTerms": [
                    {
                        "type": "simple",
                        "pattern": fixedSearchTerm,
                        "caseSensitive": false,
                        "termId": "0"
                    }
                ]
            }
        }),
        "contentType": "application/json",
        "success": function(response) {
            $.ajax({
                "url": pasUrl + "/v2/searchTasks/" + response["processId"] + "/results?limit=1",
                "success": function(response) {
                    if (response.results.length !== 0) {
                        searchReady = true;

                        displaySearchIfNeeded();
                    }
                },
            });
        },
        "error": function(jqXHR, textStatus, errorThrown) {
            if (jqXHR.status === 480) {
                setTimeout(sendSearchPost, 2000);
            }
        }
    });
};

setTimeout(sendSearchPost, 500);

$(document).ready(function() {
    // Since we are no longer restricted to a predefined search, we can load the viewer ASAP.
    viewer = $("#viewer").pccViewer({
        "documentID": viewingSessionId,
        "imageHandlerUrl": "/pas",
        "language": viewerCustomizations.languages["en-US"],
        "template": viewerCustomizations.template,
        "icons": viewerCustomizations.icons
    });

    viewer.viewerControl.on("ViewerReady", function(event) {
        viewerReady = true;

        displaySearchIfNeeded();
    });
});
Question

When viewing .csv files in PrizmDoc Viewer, the dates in the CSV file are in UK format (DD/MM/YYYY). However, if the DD is lower than 13 it is converted to US date format (MM/DD/YYYY).

Answer

Workaround:

The suggested workaround is to use Excel files instead of CSV to avoid this situation. Excel file format stores date/time format in the file.

Issue:

This is a bug in the MS Excel COM Interop that is being used by the product (MsOfficeConverter). Here is the related Excel bug: https://social.msdn.microsoft.com/Forums/vstudio/en-US/82248560-dabd-4c90-b1e2-793b2f32b257/excel-bug-handling-dates-in-csv-files-using-microsoftofficeinteropexcel?forum=exceldev

Problem description:

When using MS Excel Interop to open CSV files, all date/times there are being interpreted with “en-US” locale, regardless of actual system locale. Here is the description from the bug link above:

Excel interpreting dates when its reads csv files via .NET Interop. It is not a excel formatting issue per say. When excel accesses information such as dates (which are stored as numbers in memory to support arithmetic operations) from text files, it has to convert the date from textual representation (within the csv file, such as 2012-09-12) to the equivalent number in Excel memory (e.g. 41164 which represents 2012-09-12). When we use Interop to access this number in memory, many are interpreted incorrectly – swapping days with months and vice versa. This is a bug, as Excel is not abiding by the system culture on interpreting local date formats.

Question

We are saving files to the PDF/A standard and are running into a few cases where the file cannot be saved as PDF/A by ImageGear .NET. Why is this, and how do we do it properly?

Answer

First, determine whether a PDF document can be converted to PDF/A by creating an ImGearPDFPreflight object from your document, and generating an ImGearPDFPreflightReport object from it:

using (ImGearPDFPreflight preflight = new ImGearPDFPreflight((ImGearPDFDocument)igDocument))
{
    report = preflight.VerifyCompliance(ImGearPDFPreflightProfile.PDFA_1A_2005, 0, -1);
}

The first argument of the VerifyCompliance() method is the standard of PDF/A you want to use. ImageGear .NET is currently able to convert documents to adhere to the PDF/A-1A and PDF/A-1B standards:

PDF/A-1 Standard

ImageGear and PDF/A

There are parts of the PDF/A-2 and PDF/A-3 standards which may allow for more documents to be converted, but ImageGear .NET currently does not support those. This could possibly be why your document cannot be converted in ImageGear .NET.

Once the report is generated, you can access its Status, which will tell you if the document is fixable. You can also access its Code which will let you know if it’s a fixed page or if it has issues; it will return Success if fixed, or some error code otherwise. You can check these conditions to determine whether it’s worth attempting to convert the document:

// If the document is not already PDFA-1a compliant but can be converted
if ((report.Code == ImGearPDFPreflightReportCodes.SUCCESS) ||
(report.Status == ImGearPDFPreflightStatusCode.Fixable))
{
    ImGearPDFPreflightConvertOptions pdfaOptions = new ImGearPDFPreflightConvertOptions(ImGearPDFPreflightProfile.PDFA_1A_2005, 0, -1);
    ImGearPDFPreflight preflight = new ImGearPDFPreflight((ImGearPDFDocument)igDocument);
    preflight.Convert(pdfaOptions);
    saveFile(outputPath, igDocument);
}

// Create error message if document was not converted.
else if (report.Status != ImGearPDFPreflightStatusCode.Fixed)
{
    printAllRecordDescriptions(report);
    throw new ApplicationException("Given PDF document cannot be converted to PDFA-1a standard.");
}

If you want more information on why a document may not be convertible, you can access the preflight report for its records and codes. A preflight’s "Records" member is a recursive list of preflight reports. A preflight report will have a list of reports under Records, and each of those reports may have more reports, etc. You can recursively loop through them as seen below to output every reason a document is not convertible:

    private static void printAllRecordDescriptions(StreamWriter file, ImGearPDFPreflightReport report)
    {
        foreach (ImGearPDFPreflightReport rep in report.Records)
        {
            file.WriteLine(rep.Description);
            file.WriteLine(rep.Code.ToString() + "\r\n");
            printAllRecordDescriptions(file, rep);
        }
    }

Ultimately, the failure of a document to convert to PDF/A is non-deterministic. While some compliance failures can be corrected, in combination they may not be correctable. Therefore, the unfortunate answer is that to determine if it can be converted, conversion must be attempted.

Question

When looking at the configuration files for both PAS (pcc.win.yml, pcc.nix.yml) and PrizmDoc Server (prizm-services-config.yml), there appear to be similar settings for Viewing Session timeouts: defaults.viewingSessionTimeout (PAS) and viewing.sessionLifetime (Server). What is the difference between the two?

Answer

The difference is as follows:

PAS

defaults.viewingSessionTimeout

This setting is used when the viewing session POST requests use source.type="viewingPackage".

Prizm Server

viewing.sessionLifetime

This setting is used for all other viewing session POST requests.

Question

When loading PDF documents into PrizmDoc that contain embedded highlights, rather than appearing translucent, the highlights are appearing opaque and are covering the underlying text. Why is this happening?

Answer

Prior to version 13.4 of PrizmDoc, this was occurring due to limitations in web browsers. The SVG attribute comp-op="multiply" was not widely supported in modern browsers.

With PrizmDoc version 13.4, the way highlights were rendered was changed to resolve this issue.

Question

When printing non-standard size raster images with PrizmDoc they can sometimes become cutoff if too tall or wide. How can I correctly print a non-standard size raster image with PrizmDoc?

Answer

(This explanation is done for a tall portrait image, but can be altered to work for a wide landscape image by flipping the width and height.)

To do this, you have to add a custom paper size to viewerCustomization.js and specify a smaller width so that there is enough room to fit the height of the image on a single page.

To find the correct width value so that the image will fit on a single page, you will need to do some math. In this example, we’ll use an image that is 1305×2823. In this case, the width is 46.2% of the height. If you want to print onto 8.5×11 inch paper, then the width you want to set for your new custom paper size is 11*0.462, which comes out to 5.082.

So now that you have the width, you need to create the new custom paper size. In viewerCustomization.js in the templates section, find the "print" template and add the following code where the other printing paper sizes are located.

/*custom */
.portrait .custom.page { width: 5.082in; height: 11in; margin: 0 auto !important; }
.portrait .custom.pageIE { width: 9.5in; height: 9.5in; margin: 0 auto !important; }
.portrait .custom.pageSafari { width: 8.9in; height: 8.9in; margin: 0 auto !important; }
.portrait .custom.nomargins { width: 11in !important; height: 11in !important; }

/* even without margins, Safari enforces the printer's non-printable area */
.portrait .custom.nomargins.pageSafari { width: 9.32in !important; height: 9.32in !important; }

.landscape .custom.page { height: 5.082in; width: 11in; margin: 0 auto !important; }
.landscape .custom.pageIE { height: 9.05in; width: 9.05in; margin: 0 auto !important; }
.landscape .custom.pageSafari { height: 8.4in; width: 8.4in; margin: 0 auto !important; }
.landscape .custom.nomargins { height: 11in !important; width: 11in !important; }
.landscape .custom.nomargins.pageSafari { height: 9.32in !important; width: 9.32in !important; }
/*custom end*/

As you can see, the width for .portrait .custom.page was set to 5.082in, and the height set to 11in. This will scale the 1305×2823 image to fit on a single 8.5×11 page when printing. By flipping the values and setting them in .landscape you would be able to print a 2823×1305 image on a single landscape page. (Just to note, I only edited the values for .custom.page for portrait and landscape. The others would most likely need to be changed.)

Next you need to add an option for your new paper size to the "paperSize" selection tag in the "printOverlay" section of templates in viewerCustomization.js. Your select tag should end up looking something like this:

<select data-pcc-select="paperSize" class="pcc-print-select">
    <!-- US and International-->
    <option value="letter"><%= paperSizes.letter %></option>
    <option value="legal"><%= paperSizes.legal %></option>
    <option value="tabloid"><%= paperSizes.tabloid %></option>
    <option value="foolscap"><%= paperSizes.foolscap %></option>
    <!-- A formats-->
    <option value="a3"><%= paperSizes.a3 %></option>
    <option value="a4"><%= paperSizes.a4 %></option>
    <option value="a5"><%= paperSizes.a5 %></option>
    <!-- Architectural-->
    <option value="a6"><%= paperSizes.a6 %></option>
    <option value="a"><%= paperSizes.a %></option>
    <option value="b"><%= paperSizes.b %></option>
    <option value="c"><%= paperSizes.c %></option>
    <option value="d"><%= paperSizes.d %></option>
    <option value="e"><%= paperSizes.e %></option>
    <option value="e1"><%= paperSizes.e1 %></option>
        
    <option value="custom">Custom</option>
</select>

The new print option should now appear in the PrizmDoc print settings when selecting a paper size, and it should print the image on a single page.

One thing to note is that you will have to do this for each differently sized image. If you are unsure of the size of uploaded documents, this solution will most likely not be usable.

Question

After searching a document, an error icon appears in the search results panel. Clicking on it displays the following error message: “x page(s) cannot be searched.” Why does this occur and how can I find out which specific pages couldn’t be searched?

Answer

When the PrizmDoc Viewer text-service cannot find any text for a given page in the document, it provides an array of all the pages without text in the response from searchTask results.

In short, the document is fine and simply contains pages without text. If you look at the pagesWithoutText array contained within the response data from searchTasks, you’ll see something like this:

[0, 1, 7, 17, 43, 45, 65, 67, 77, 79,…]

The values reported are pages that do not contain any text but instead are either blank or contain an image. This data can then be used to inform the user of how many pages are not searchable.