Load document mode.
lt.Document.DocumentLoadMode = {
service: 0,
local: 1,
localThenService: 2
}
Value | Member | Description |
---|---|---|
service | 0 | Always call the service. This is default behavior. |
local | 1 | Try to load the document locally in the client without calling the service. |
localThenService | 2 | Try to load the document locally; if that fails, try to load it using the service. |
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.
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":
// 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":
// 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:
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":
// 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();
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.
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:
// 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.
// 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.
// 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:
// 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.
DocumentFactory.loadFromUri uses XMLHttpRequest
to download the document from the external resources. During the run of this method, the factory will check the following:
DocumentLoadOptions.loadMode
was set to local
or localThenService
DocumentFactory.localProxyUrlTemplate
is not null or emptyWhen 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
You can use the helper method DocumentFactory.buildUrlProxy to obtain this URL using the current proxy template setting:
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.
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:
// 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.