Hi I'm trying to add cookies to the http headers when generating a pdf file with abcpdf. What I have done so far is based on the documentation:
When requesting the page to be converted to PDF from my browser the headers are:
Connection: keep-alive
Accept: text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
Accept-Encoding: gzip, deflate
Accept-Language: en-ie
Cookie: __utma=111872281.2030591713.1334325919.1348754241.1349943306.47; __utmz=111872281.1334325919.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); CurrentClient=AMF; UserHasMultipleClients=False; favFunds=%5B%7B%22id%22%3A57%2C%22alias_id%22%3A1690%7D%2C%7B%22id%22%3A794%2C%22alias_id%22%3Anull%7D%2C%7B%22id%22%3A818%2C%22alias_id%22%3Anull%7D%2C%7B%22id%22%3A21%2C%22alias_id%22%3Anull%7D%5D; favComparisons=%5B%7B%22selectedFunds%22%3A%5B%7B%22id%22%3A%22794%22%2C%22alias%22%3A%22null%22%7D%2C%7B%22id%22%3A%2217%22%2C%22alias%22%3A%22null%22%7D%2C%7B%22id%22%3A%22593%22%2C%22alias%22%3A%22old%22%7D%2C%7B%22id%22%3A%22593%22%2C%22alias%22%3A%221606%22%7D%5D%2C%22selectedIndexes%22%3A%5B%7B%22id%22%3A%2224002259%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22timePeriosSelection%22%3A%7B%22dateOne%22%3A%2223-11-2011%22%2C%22dateTwo%22%3A%2223-11-2012%22%7D%2C%22defaultTimePeriodSelection%22%3A%7B%22OneYear%22%3Atrue%2C%22ThreeYears%22%3Afalse%2C%22FiveYears%22%3Afalse%7D%7D%2C%7B%22selectedFunds%22%3A%5B%7B%22id%22%3A%22774%22%2C%22alias%22%3A%22null%22%7D%2C%7B%22id%22%3A%22215%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22selectedIndexes%22%3A%5B%7B%22id%22%3A%2224002259%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22timePeriosSelection%22%3A%7B%22dateOne%22%3A%2223-11-2011%22%2C%22dateTwo%22%3A%2223-11-2012%22%7D%2C%22defaultTimePeriodSelection%22%3A%7B%22OneYear%22%3Atrue%2C%22ThreeYears%22%3Afalse%2C%22FiveYears%22%3Afalse%7D%7D%2C%7B%22selectedFunds%22%3A%5B%7B%22id%22%3A%22215%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22selectedIndexes%22%3A%5B%7B%22id%22%3A%2224002259%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22timePeriosSelection%22%3A%7B%22dateOne%22%3A%2223-11-2011%22%2C%22dateTwo%22%3A%2223-11-2012%22%7D%2C%22defaultTimePeriodSelection%22%3A%7B%22OneYear%22%3Atrue%2C%22ThreeYears%22%3Afalse%2C%22FiveYears%22%3Afalse%7D%7D%5D
Host: localhost:63706
Referer: http://localhost:63706/
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20100101 Firefox/15.0.1
X-Requested-With: XMLHttpRequest
When the request comes from abcpdf the headers by are:
Connection: keep-alive
Keep-Alive: 115
Accept: text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
Accept-Charset: ISO-8859-1, utf-8; q=0.7, *; q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: en-us, en; q=0.5
Host: localhost:63706
Referer: http://localhost:63706/
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/ /2.0.1
X-Requested-With: XMLHttpRequest
As you can see it is missing the cookies. So I manually aded the following to the headers(theDoc.HtmlOptions.HttpAdditionalHeaders value before abcpdf send request)
Cookie: __utma=111872281.2030591713.1334325919.1348754241.1349943306.47; __utmz=111872281.1334325919.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); CurrentClient=AMF; UserHasMultipleClients=False; favFunds=%5B%7B%22id%22%3A57%2C%22alias_id%22%3A1690%7D%2C%7B%22id%22%3A794%2C%22alias_id%22%3Anull%7D%2C%7B%22id%22%3A818%2C%22alias_id%22%3Anull%7D%2C%7B%22id%22%3A21%2C%22alias_id%22%3Anull%7D%5D; favComparisons=%5B%7B%22selectedFunds%22%3A%5B%7B%22id%22%3A%22794%22%2C%22alias%22%3A%22null%22%7D%2C%7B%22id%22%3A%2217%22%2C%22alias%22%3A%22null%22%7D%2C%7B%22id%22%3A%22593%22%2C%22alias%22%3A%22old%22%7D%2C%7B%22id%22%3A%22593%22%2C%22alias%22%3A%221606%22%7D%5D%2C%22selectedIndexes%22%3A%5B%7B%22id%22%3A%2224002259%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22timePeriosSelection%22%3A%7B%22dateOne%22%3A%2223-11-2011%22%2C%22dateTwo%22%3A%2223-11-2012%22%7D%2C%22defaultTimePeriodSelection%22%3A%7B%22OneYear%22%3Atrue%2C%22ThreeYears%22%3Afalse%2C%22FiveYears%22%3Afalse%7D%7D%2C%7B%22selectedFunds%22%3A%5B%7B%22id%22%3A%22774%22%2C%22alias%22%3A%22null%22%7D%2C%7B%22id%22%3A%22215%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22selectedIndexes%22%3A%5B%7B%22id%22%3A%2224002259%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22timePeriosSelection%22%3A%7B%22dateOne%22%3A%2223-11-2011%22%2C%22dateTwo%22%3A%2223-11-2012%22%7D%2C%22defaultTimePeriodSelection%22%3A%7B%22OneYear%22%3Atrue%2C%22ThreeYears%22%3Afalse%2C%22FiveYears%22%3Afalse%7D%7D%2C%7B%22selectedFunds%22%3A%5B%7B%22id%22%3A%22215%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22selectedIndexes%22%3A%5B%7B%22id%22%3A%2224002259%22%2C%22alias%22%3A%22null%22%7D%5D%2C%22timePeriosSelection%22%3A%7B%22dateOne%22%3A%2223-11-2011%22%2C%22dateTwo%22%3A%2223-11-2012%22%7D%2C%22defaultTimePeriodSelection%22%3A%7B%22OneYear%22%3Atrue%2C%22ThreeYears%22%3Afalse%2C%22FiveYears%22%3Afalse%7D%7D%5D
This is the full code:
public MemoryStream HtmlToPdf(Uri pdfUrl, HttpCookieCollection cookies, bool landscape)
{
var pdfStream = new MemoryStream();
var theDoc = new Doc();
if (landscape)
{
// apply a rotation transform
double w = theDoc.MediaBox.Width;
double h = theDoc.MediaBox.Height;
double l = theDoc.MediaBox.Left;
double b = theDoc.MediaBox.Bottom;
theDoc.Transform.Rotate(90, l, b);
theDoc.Transform.Translate(w, 0);
// rotate our rectangle
theDoc.Rect.Width = h;
theDoc.Rect.Height = w;
}
theDoc.HtmlOptions.Engine = EngineType.Gecko;
theDoc.HtmlOptions.Timeout = 60000;
theDoc.HtmlOptions.UseScript = true;
theDoc.HtmlOptions.OnLoadScript = "(function(){window.ABCpdf_go = false; setTimeout(function(){window.ABCpdf_go = true;}, 1000);})();";
var url = Uri.UnescapeDataString(pdfUrl.ToString());
if (cookies.Count > 0)
{
//send copy of cookies from original request
var additionalHeadersString = "Cookie: ";
foreach (var key in cookies.AllKeys)
{
if (!cookies.AllKeys[0].Equals(key)) //is NOT first element in cookie collection
{
additionalHeadersString += "; ";
}
additionalHeadersString += key + "=" + cookies[key].Value;
}
additionalHeadersString += "\r\n";
theDoc.HtmlOptions.HttpAdditionalHeaders = additionalHeadersString;
theDoc.HtmlOptions.NoCookie = true;
theDoc.HtmlOptions.HostWebBrowser = false;
}
//send request
var pageRef = theDoc.AddImageUrl(url, true, 1200, false);
while (theDoc.Chainable(pageRef))
{
theDoc.Page = theDoc.AddPage();
pageRef = theDoc.AddImageToChain(pageRef);
}
for (var i = 1; i <= theDoc.PageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
theDoc.Save(pdfStream);
theDoc.Clear();
var byteInfo = pdfStream.ToArray();
pdfStream.Write(byteInfo, 0, byteInfo.Length);
pdfStream.Position = 0;
return pdfStream;
}
The problem is that the cookies still missing from the header after using the HttpAdditionalHeaders property, do you know what I'm missing?
Thanks in advance :)
Here the solution and why it didn't work:
Why it didn't work?
AbcPdf does NOT support theDoc.HtmlOptions.HttpAdditionalHeaders
when using Gecko as rendering engine.
Work arround
Action that will generate PDF given an URL:
public class PdfController : Controller
{
private readonly IPdfGenerator _pdfGenerator;
public PdfController(IPdfGenerator pdfGenerator)
{
if (pdfGenerator == null)
throw new ArgumentNullException();
this._pdfGenerator = pdfGenerator;
}
public FileStreamResult Index(string url)
{
Response.AppendHeader("Content-Disposition", "attachment;filename=Download.Pdf");
this._pdfGenerator.SetCookies(Request.Cookies);
return new FileStreamResult(_pdfGenerator.HtmlToPdf(url.Uri, false, 1200), "application/pdf");
}
}
PDF generation class:
public class AbcPdfGenerator : IPdfGenerator
{
private static HttpCookieCollection _cookies = new HttpCookieCollection();
public void SetCookies(HttpCookieCollection cookies)
{
lock (_cookies)
{
_cookies = cookies;
System.Threading.Thread.MemoryBarrier();
}
}
public HttpCookieCollection GetCookies()
{
return _cookies;
}
public MemoryStream HtmlToPdf(Uri pdfUrl, bool landscape, int screenResolutionWidth, bool enableCache)
{
var pdfStream = new MemoryStream();
var theDoc = new Doc();
if (landscape)
{
// apply a rotation transform
double w = theDoc.MediaBox.Width;
double h = theDoc.MediaBox.Height;
double l = theDoc.MediaBox.Left;
double b = theDoc.MediaBox.Bottom;
theDoc.Transform.Rotate(90, l, b);
theDoc.Transform.Translate(w, 0);
// rotate our rectangle
theDoc.Rect.Width = h;
theDoc.Rect.Height = w;
}
theDoc.HtmlOptions.Engine = EngineType.Gecko;
theDoc.HtmlOptions.Timeout = 60000;
theDoc.HtmlOptions.UseScript = true;
theDoc.HtmlOptions.OnLoadScript = "(function(){window.ABCpdf_go = false; setTimeout(function(){window.ABCpdf_go = true;}, 3000);})();";
var url = Uri.UnescapeDataString(pdfUrl.ToString());
var pageRef = theDoc.AddImageUrl(url, true, screenResolutionWidth, enableCache);
while (theDoc.Chainable(pageRef))
{
theDoc.Page = theDoc.AddPage();
pageRef = theDoc.AddImageToChain(pageRef);
}
for (var i = 1; i <= theDoc.PageCount; i++)
{
theDoc.PageNumber = i;
theDoc.Flatten();
}
theDoc.Save(pdfStream);
theDoc.Clear();
var byteInfo = pdfStream.ToArray();
pdfStream.Write(byteInfo, 0, byteInfo.Length);
pdfStream.Position = 0;
return pdfStream;
}
/// <summary>
/// Will install the pdf software license on the server, this should be called on a Application_Start()
/// </summary>
public void InitializeService()
{
XSettings.InstallLicense(System.Configuration.ConfigurationManager.AppSettings["PdfGeneratorLicenseKey"]);
//XSettings.InstallTrialLicense(System.Configuration.ConfigurationManager.AppSettings["PdfGeneratorLicenseKey"]);
}
}
Action that return HTML to be converted to PDF:
[RequireCookiesForPdf]
public ActionResult Index(string layout)
{
return View();
}
The action filter used before:
public class RequireCookiesForPdf : ActionFilterAttribute
{
private readonly IPdfGenerator _pdfGenerator;
public RequireCookiesForPdf()
{
//"Bastard injection" :( as action filters don't allow constructor injection
this._pdfGenerator = DependencyResolver.Current.GetService<IPdfGenerator>();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var cookies = this._pdfGenerator.GetCookies();
if (cookies != null)
{
foreach (var key in cookies.AllKeys)
{
var httpCookie = cookies[key];
if (httpCookie != null) filterContext.HttpContext.Response.Cookies.Set(new HttpCookie(key, httpCookie.Value));
}
this._pdfGenerator.SetCookies(new HttpCookieCollection());
}
base.OnActionExecuting(filterContext);
}
}