|
Rank: Newbie Groups: Member
Joined: 1/23/2019 Posts: 3
|
We have a .NET webservice where we use HtmlToPdf.Convert method of EO.PDF to convert a web page into a PDF. The URL of the web page is always the same but we pass different querystring value each time. so the web page loads different form in each run. However, it seems that local-storage and session-storage values are being retained between consecutive PDF conversions. We are looking to run each PDF conversion in private or incognito mode, so that local-storage and session-storage are not shared across multiple runs.
We have already tried a few things: 1.We tried to set a new CacheFolder for each run but CacheFolder is a static property and cannot be changed until we restart the webservice. 2. We tried to force delete the CacheFolder after reach run, but it failed with error that the files are in use. 2. We tried creating a new instance of EO.WebEngine.Engine for each run, but there is no way to assign the new engine to HtmlToPdf at runtime. 3. We tried HTMLtoPDFSession with using block, but still the local-storage and session-storage values did not get disposed before the next run.
How can we set incognito mode during PDF conversion, or can we achieve this by using some other approach? Please suggest.
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,383
|
Hi, For performance reasons, internally EO.Pdf uses a pool of WebView objects for conversion. So it will always reuse WebViews. However it is possible for you to disable both localStorage and cache even if WebViews are reused. To disable localStorage, you can use HtmlToPdfOptions.JSInitCode to explicitly override window.localStorage to a non-functioning one. For example:
Code: C#
HtmlToPdfOptions options = new HtmlToPdfOptions();
//This runs JSInitCode inside the WebView before a page is being loaded.
//The code here replaces the built-in window.localStorage interface with
//a non-functioning version where getItem always returns null and setItem
//does nothing
options.JSInitCode = @"
Object.defineProperty(window, 'localStorage', {
configurable: false,
enumerable: true,
value: {
getItem: function (sKey) { return null; },
setItem: function (sKey, sValue) {}
}
});";
using (HtmlToPdfSession session = HtmlToPdfSession.Create(options))
{
//Perform the conversion
session.LoadUrl(url);
session.RenderAsPDF(result_pdf_file);
}
To disable cache, you can handle the internal WebView's BeforeRequestLoad event to explicitly add Cache-Control header entry to disable the cache. For example:
Code: C#
using (HtmlToPdfSession session = HtmlToPdfSession.Create(options))
{
BeforeRequestLoadHandler handler = (sender, e) =>
{
e.Request.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate";
};
//Attach BeforeRequestLoad handler
session.RunWebViewCallback(() =>
{
session.WebView.BeforeRequestLoad += handler;
});
//Perform conversion
session.LoadUrl(url);
session.RenderAsPDF(result_pdf_file);
//Detach BeforeRequestLoad handler
session.RunWebViewCallback(() =>
{
session.WebView.BeforeRequestLoad -= handler;
});
}
Please let us know if this works for you. Thanks!
|
|
Rank: Newbie Groups: Member
Joined: 1/23/2019 Posts: 3
|
Hi, Thank you for your response. We have to make use of localstorage, so we cannot fully disable it. Your suggestion inspired me to use a custom localstorage each time, as shared in code below. Do you see this as a feasible solution or can it have potential issues? Please advise.
Code: C#
HtmlToPdf.Options.JSInitCode = @"
Object.defineProperty(window, 'localStorage', {
configurable: false,
enumerable: true,
value: (function() {
const customStorage = {};
return {
getItem: function (sKey) {
return Object.prototype.hasOwnProperty.call(customStorage, sKey) ? customStorage[sKey] : null;
},
setItem: function (sKey, sValue) {
customStorage[sKey] = String(sValue);
},
removeItem: function (sKey) {
delete customStorage[sKey];
},
clear: function () {
for (const key in customStorage) {
if (Object.prototype.hasOwnProperty.call(customStorage, key)) {
delete customStorage[key];
}
}
},
get length() {
return Object.keys(customStorage).length;
},
key: function(index) {
return Object.keys(customStorage)[index] || null;
}
};
})()
});";
|
|
Rank: Administration Groups: Administration
Joined: 5/27/2007 Posts: 24,383
|
Yes. This will work as long as you are not planing to share localStorage between pages --- including iframes.
|
|