2

嗨,我正在尝试在使用 abcpdf 生成 pdf 文件时将 cookie 添加到 http 标头。到目前为止我所做的是基于文档:

http://www.websupergoo.com/helppdf9net/default.htm?page=source%2F5-abcpdf%2Fxhtmloptions%2F2-properties%2Fhttpadditionalheaders.htm

从我的浏览器请求将页面转换为 PDF 时,标题为:

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

当请求来自 abcpdf 时,标头为:

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

如您所见,它缺少 cookie。所以我手动将以下内容添加到标题中(abcpdf 发送请求之前的 theDoc.HtmlOptions.HttpAdditionalHeaders 值)

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

这是完整的代码:

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;
}

问题是使用 HttpAdditionalHeaders 属性后,标头中仍然缺少 cookie,您知道我缺少什么吗?

提前致谢 :)

4

2 回答 2

1

这是解决方案以及为什么它不起作用:

为什么它不起作用?

theDoc.HtmlOptions.HttpAdditionalHeaders使用 Gecko 作为渲染引擎时,AbcPdf 不支持。

工作区

给定 URL 将生成 PDF 的操作:

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生成类:

    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"]);
        }
    }

返回要转换为 PDF 的 HTML 的操作:

[RequireCookiesForPdf]
public ActionResult Index(string layout)
{
    return View();
}

之前使用的动作过滤器:

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);
    }
}
于 2012-12-06T12:00:03.327 回答
1

theDoc.HtmlOptions.HttpAdditionalHeaders使用Gecko作为渲染引擎时, AbcPdf不支持....

在 Gecko 下,仅当您使用 Screen Media 或使用 POST 时才会发送这些标头RequestMethod。例如:

theDoc.HtmlOptions.Media = MediaType.Screen;

问候!

于 2016-08-04T18:20:54.223 回答