DocumentLoadMode Enumeration

Summary

Load document mode.

Syntax
TypeScript
JavaScript
lt.Document.DocumentLoadMode = { 
   service: 0, 
   local: 1, 
   localThenService: 2 
} 
lt.Document.DocumentLoadMode = { 
   service: 0, 
   local: 1, 
   localThenService: 2 
} 

Members

ValueMemberDescription
service0Always call the service. This is default behavior.
local1Try to load the document locally in the client without calling the service.
localThenService2Try to load the document locally; if that fails, try to load it using the service.

Remarks

DocumentLoadMode is used as the type for the LoadDocumentOptions.loadMode property.

The document library supports loading some file formats locally without requiring a service. Currently this support is limited to the following:

  • PDF: Adobe Portable Document Format

  • JPEG, PNG, and GIF: Standard web formats and any other file format supported natively by the browser.

Later versions of the document library will add support for more formats.

Documents are loaded from external URLs or files using DocumentFactory.loadFromUri. This method accepts parameter options of type LoadDocumentOptions which contains the loadMode property.

The default value of this property is DocumentLoadMode.service. This instructs the library to load the document using the document service (set in DocumentFactory.serviceHost).

When the value of loadMode is set to local, the library tries to load the URL or file without contacting the service. The data in the file must be one of the supported file formats described above; otherwise, the load operation fails.

When the value of loadMode is set to localThenService, the library tries to load the URL or file without contacting the service (similar to local). If not successful, it then tries to load the file using the service (similar to service).

Local documents that are loaded successfully cannot be shared in a multi-user application and only exist in the local browser. The document library will automatically upload the document to the service when operations such as DocumentFactory.saveToCache (to save it to the cache) or StatusJobDataRunner are used (to convert it to a different file format).

Some JavaScript environments do not support loading external resources at all. Other environments require CORS support on the server that the original resource might not provide. Therefore, a proxy may be required to redirect the calls between DocumentFactory and the external resources. The application can use any standard CORS proxy and set its template in DocumentFactory.localProxyUrlTemplate. The LEADTOOLS Document Service provides such a proxy that can be used. For more information, refer to the following section, or any of the DocumentService examples in your LEADTOOLS installation.

Cross-Origin Resource Sharing (CORS)

CORS is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts.

Assume this JavaScript source code is running at http://server1.com/app and the resource (in this instance, an image), is on a completely different server at http://server2.com/images/image.png. Assume that server2 does not have CORS enabled.

The following code uses an HTML img element and will show "OK":

JavaScript
// CORS is not enabled at server2.com 
const imageUrl = "http://server2.com/images/image.png"; 
let img = document.createElement("img"); 
img.onload = () => { alert("OK"); }; 
img.onerror = () => { alert("Error"); }; 
img.src = imageUrl; 

This code takes advantage of built-in HTML image element support for loading images from foreign origin.

However, the following code uses JavaScript XMLHttpRequest and will show "Error":

JavaScript
// CORS is not enabled at server2.com 
const imageUrl = "http://server2.com/images/image.png"; 
let xhr = new XMLHttpRequest(); 
xhr.open("GET", imageUrl); 
xhr.onload = () => { alert("OK"); }; 
xhr.onerror = () => { alert("Error"); }; 
xhr.send(); 

This code attempts a cross-origin request, and as explained in the CORS documentation, cross-origin requests are not allowed. As well as the alert from the source code above, an error is thrown into the browser console:

Access to XMLHttpRequest at 'http://server2.com/images/image.png' from origin 'http://server1.com/app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

There are multiple ways to fix this issue:

CORS Enabled on the Server

Ensure that the server containing the resource has CORS enabled.

For instance, https://demo.leadtools.com has CORS enabled, and if you modify the code as follows then the code will show "OK":

JavaScript
// CORS is not enabled at server2.com 
// const imageUrl = " http://server2/images/image.png"; 
// However, CORS is enabled at demo.leadtools.com 
const imageUrl = "https://demo.leadtools.com/images/pdf/leadtools.pdf"; 
let xhr = new XMLHttpRequest(); 
xhr.open("GET", imageUrl); 
xhr.onload = () => { alert("OK"); }; 
xhr.onerror = () => { alert("Error"); }; 
xhr.send(); 

Use CORS Proxy

If the resource is on a server that we do not have access to, or if security policies prevent us from enabling CORS on the server then we could use a CORS proxy.

A CORS proxy is a simple forwarding web service that acts as a gateway between the browser and the resources to bypass CORS.

DocumentLoadMode.local and CORS

The LEADTOOLS DocumentService contains a CORS proxy end point in the CorsProxy controller. This endpoint allows the user to bypass CORS errors when using the local or localThenService modes. The user can also use the user's own CORS proxy, if required.

Start with the following code that loads a PDF document using local mode:

JavaScript
// Loads a document using LoadDocumentOptions.local 
function loadDocumentUsingLocal(documentUrl) { 
   // This is the LEADTOOLS DocumentService 
   const serviceHost = "http://localhost:40000"; 
 
   // Set up the DocumentFactory service properties 
   lt.Document.DocumentFactory.serviceHost = serviceHost; 
   lt.Document.DocumentFactory.servicePath = ""; 
   lt.Document.DocumentFactory.serviceApiPath = "api"; 
 
   // Do not use a proxy 
   lt.Document.DocumentFactory.localProxyUrlTemplate = ""; 
 
   const loadDocumentOptions = new lt.Document.LoadDocumentOptions(); 
   // Use local mode 
   loadDocumentOptions.loadMode = lt.Document.DocumentLoadMode.local; 
   lt.Document.DocumentFactory.loadFromUri(documentUrl, loadDocumentOptions) 
      .done((leadDocument) => { 
         alert("Document loaded: " + leadDocument.mimeType); 
      }) 
      .fail((jqXHR, statusText, errorThrown) => { 
         alert("Error returned from service. See the console for details."); 
         const serviceError = lt.Document.ServiceError.parseError(jqXHR, statusText, errorThrown); 
         console.log(serviceError); 
      }); 
} 

If you call this function with a resource that has CORS enabled on the server, such as https://demo.leadtools.com/images/pdf/leadtools.pdf, it will work and the "Document loaded" alert will appear.

JavaScript
// demos.leadtools.com has CORS Enabled 
loadDocumentUsingLocal("https://demo.leadtools.com/images/pdf/leadtools.pdf"); 

Now, if you call this function with a resource that does not have CORS enabled on the server, such as, http://server2.com/images/pdf/leadtools.pdf, it will not work and the "Error ..." alert will appear.

JavaScript
// server2.com does not have CORS Enabled 
loadDocumentUsingLocal("http://server2.com/images/pdf/leadtools.pdf"); 

Checking the browser console log will show the error as well:

Access to XMLHttpRequest at 'http://server2.com/images/pdf/leadtools.pdf' from origin 'http://server1.com/app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

To fix this issue, use a CORS Proxy. LEADTOOLS DocumentService contains the CorsProxy controller that can be used for this purpose. To enable it, modify the following line in the sample code:

JavaScript
// Do not use a proxy 
//lt.Document.DocumentFactory.localProxyUrlTemplate =""; 
// Use DocumentService's own CORS proxy 
lt.Document.DocumentFactory.localProxyUrlTemplate = serviceHost + "/api/CorsProxy/Proxy?{0}"; 

Call the function again and the document will load correctly.

Under the Hood

DocumentFactory.loadFromUri uses XMLHttpRequest to download the document from the external resources. During the run of this method, the factory will check the following:

  • If DocumentLoadOptions.loadMode was set to local or localThenService
  • If DocumentFactory.localProxyUrlTemplate is not null or empty

When both of these conditions are met, the factory will replace {0} in the template with the value of the URL and send this to XMLHttpRequest instead. Therefore, using the code from the sample before this, the actual resources requested by XHR is:

http://localhost:40000/api/CorsProxy/Proxy?&url=http://server2.com/images/pdf/leadtools.pdf&userData=null
Note that userData is passed with each request as described here.

You can use the helper method DocumentFactory.buildUrlProxy to obtain this URL using the current proxy template setting:

JavaScript
const serviceHost = "http://localhost:40000"; 
lt.Document.DocumentFactory.localProxyUrlTemplate = serviceHost + "/api/CorsProxy/Proxy?{0}"; 
const imageUrl = "http://server2.com/images/pdf/leadtools.pdf"; 
const imageUrlWithProxy = lt.Document.DocumentFactory.buildUrlProxy(imageUrl); 
console.log(imageUrlWithProxy); 

Will print into the console:

http://localhost:40000/api/CorsProxy/Proxy?&url=http://server2.com/images/pdf/leadtools.pdf&userData=null`

If 3rd party CORS proxy are to be used, then localProxyUrlTemplate must be updated to the correct template.

The source code for DocumentService is provided in your LEADTOOLS installation. See the example for the CorsProxy controller for more information.

Customizing CorsProxy

The prepareAjax event can be used to inspect and modify all XMLHttpRequest calls made by the DocumentFactory, including CorsProxy calls.

The following complete example shows how to hook into the prepareAjax event to inject a custom header setting to pass to the external resources:

JavaScript
// server2.com does not have CORS enabled 
const documentUrl = "http://server2.com/images/pdf/leadtools.pdf"; 
loadDocumentUsingLocalCustomized(documentUrl); 
 
// Loads a document using LoadDocumentOptions.local and sending custom headers to the server 
function loadDocumentUsingLocalCustomized(documentUrl) { 
    // This is the LEADTOOLS DocumentService 
    const serviceHost = "http://localhost:40000"; 
 
    // Set up the DocumentFactory service properties 
    lt.Document.DocumentFactory.serviceHost = serviceHost; 
    lt.Document.DocumentFactory.servicePath = ""; 
    lt.Document.DocumentFactory.serviceApiPath = "api"; 
 
    // Use DocumentService own CORS proxy 
    lt.Document.DocumentFactory.localProxyUrlTemplate = serviceHost + "/api/CorsProxy/Proxy?{0}"; 
 
    // Hook into the prepareAjax event to inject the custom headers 
    lt.Document.DocumentFactory.prepareAjax.add(prepareAjaxHandler); 
 
    // Load the document using local mode 
    const loadDocumentOptions = new lt.Document.LoadDocumentOptions(); 
    loadDocumentOptions.loadMode = lt.Document.DocumentLoadMode.local; 
    lt.Document.DocumentFactory.loadFromUri(documentUrl, loadDocumentOptions) 
        .done((leadDocument) => { 
           alert("Document loaded: " + leadDocument.mimeType); 
        }) 
        .fail((jqXHR, statusText, errorThrown) => { 
           alert("Error returned from service. See the console for details."); 
           const serviceError = lt.Document.ServiceError.parseError(jqXHR, statusText, errorThrown); 
           console.log(serviceError); 
    }); 
} 
 
// prepareAjax Handler, inject the custom header 
function prepareAjaxHandler(sender, e) { 
    // We are only interested in LoadDocumentUri from a local resource: 
    if (e.isLocalResource && e.sourceMethod === "LoadFromUri") { 
        console.log("Loading " + e.settings.url + " - inserting our magic in the HTTP headers"); 
        // Yes, add to the headers. If headers do not exist, initialize first 
        if (!e.settings.headers) { 
            e.settings.headers = {}; 
        } 
        e.settings.headers["user-custom-header"] = "MAGIC"; 
    } 
} 

Run this example and inspect the console log. You will see the log message and the headers should be updated before being sent to the server.

Requirements

Target Platforms

See Also

Reference

lt.Document Namespace

Help Version 20.0.2020.4.3
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2020 LEAD Technologies, Inc. All Rights Reserved.

Leadtools.Document Assembly