我使用带有以下代码的wkhtmltopdf.exe生成PDF。
string url = HttpContext.Current.Request.Url.AbsoluteUri;
//string[] strarry = sPath.Split('/');
//int lengh = strarry.Length;
var pdfUrl = HtmlToPdf(pdfOutputLocation: "~/PDF/", outputFilenamePrefix: "DT", urls: new string[] { url });
WebClient req = new WebClient();
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.ClearContent();
response.ClearHeaders();
response.Buffer = true;
Response.ContentType = "application/pdf";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + pdfUrl.ToString().Substring(6) + "\"");
byte[] data = req.DownloadData(Server.MapPath(pdfUrl.ToString()));
response.BinaryWrite(data);
File.Delete(Server.MapPath(pdfUrl.ToString()));
response.End();
和
public static string HtmlToPdf(string pdfOutputLocation, string outputFilenamePrefix, string[] urls,
string[] options = null,
string pdfHtmlToPdfExePath = "C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe")
{
string urlsSeparatedBySpaces = string.Empty;
try
{
//Determine inputs
if ((urls == null) || (urls.Length == 0))
throw new Exception("No input URLs provided for HtmlToPdf");
else
urlsSeparatedBySpaces = String.Join(" ", urls); //Concatenate URLs
string outputFolder = pdfOutputLocation;
string outputFilename = outputFilenamePrefix + "_" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss-fff") + ".PDF"; // assemble destination PDF file name
var p = new System.Diagnostics.Process()
{
StartInfo =
{
FileName = pdfHtmlToPdfExePath,
Arguments = ((options == null) ? "" : String.Join(" ", options)) + " " + urlsSeparatedBySpaces + " " + outputFilename,
UseShellExecute = false, // needs to be false in order to redirect output
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true, // redirect all 3, as it should be all 3 or none
WorkingDirectory = HttpContext.Current.Server.MapPath(outputFolder)
}
};
p.Start();
// read the output here...
var output = p.StandardOutput.ReadToEnd();
var errorOutput = p.StandardError.ReadToEnd();
// ...then wait n milliseconds for exit (as after exit, it can't read the output)
p.WaitForExit(60000);
// read the exit code, close process
int returnCode = p.ExitCode;
p.Close();
// if 0 or 2, it worked so return path of pdf
if ((returnCode == 0) || (returnCode == 2))
return outputFolder + outputFilename;
else
throw new Exception(errorOutput);
//Response.ContentType = "application/pdf";
//Response.AddHeader("content-length", theData.Length.ToString());
//if (Request.QueryString["attachment"] != null)
// Response.AddHeader("content-disposition", "attachment; filename=ExampleSite.pdf");
//else
// Response.AddHeader("content-disposition", "inline; filename=ExampleSite.pdf");
//Response.BinaryWrite(theData);
//HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception exc)
{
throw new Exception("Problem generating PDF from HTML, URLs: " + urlsSeparatedBySpaces + ", outputFilename: " + outputFilenamePrefix, exc);
}
}
从上面的代码中,PDF生成得很好。但是我有两个页面具有相同的LogIn和Logout User的URL。例如,让我们说www.xyz/pdf/brason。这个相同的URL用于LogIn和LogOut用户但是内容将根据用户登录或注销而不同。
现在当我登录并尝试使用上面的代码生成PDF它总是向我显示退出用户页面的内容。我不知道如何解决这个问题。
答案 0 :(得分:1)
我认为如果我理解正确,这是因为调用该页面的wkhtmltopdf未登录.Wkhtmltopdf有点像创建一个新的隐身浏览器窗口而没有任何登录cookie /会话,因此页面正确地认为它没有登录。您可以通过调试wkhtmltopdf调用服务器时获取的请求进行maby检查。
如果这是问题,可能很难解决。解决方案取决于您的登录系统以及您可以采取的措施来解决问题。如果您可以使用cookie复制登录,您可以自己设置登录cookie,请参阅http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf_0.10.0_rc2-doc.html#Page%20Options以获取有关如何设置cookie的更多信息。
另一个选择是首先从系统创建一个请求,该系统返回登录的HTML,然后将其保存到文件/流并将该文件/流提供给wkhtmltopdf(我猜你可以使用HttpContext来做到这一点)。 Current.Request或其他什么,我不知道。)
另一种解决方法是创建一个登录页面的重复页面,它看起来与登录页面完全相同但实际上并非如此 - 这个页面只会用于欺骗wkhtmltopdf。像www.xyz/pdf/brason?foolwkhtmltopdf=true
这样的东西然后通过调用类似if(url.ToLower() == "www.xyz/pdf/brason") {url="www.xyz/pdf/brason?foolwkhtmltopdf=true"; }
的东西来使用它。根据显示的信息,这可能存在安全风险。
希望这有帮助!
答案 1 :(得分:0)
我认为您需要在转换为html之前保存页面的输出。因为这会直接调用url并且在调用它时没有登录,所以当它转换为pdf时,它的请求得到了响应 我有同样的问题试图将webform转换为pdf,但填充的值,所以我保存响应为html和给wkhtmltopdf保存的路径作为参数
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
this.Page.RenderControl(hw);
StringReader sr = new StringReader(sw.ToString());
string htmlpath =Server.MapPath("~/htmloutput.html");
if (File.Exists(htmlpath))
{
File.Delete(htmlpath);
}
File.Create(htmlpath).Dispose();
using (TextWriter tw = new StreamWriter(htmlpath))
{
tw.WriteLine(sw.ToString());
tw.Close();
}
string path = Server.MapPath("~/wkhtmltopdf-page.pdf");
PdfConvert.ConvertHtmlToPdf(new Codaxy.WkHtmlToPdf.PdfDocument
{
Url = htmlpath,
HeaderLeft = "[title]",
HeaderRight = "[date] [time]",
FooterCenter = "Page [page] of [topage]"
}, new PdfOutput
{
OutputFilePath = path
});
你可以通过按钮点击事件来调用它。只在asp.net webforms上测试过。在asp.net mvc上你需要一些其他方法来获取视图html输出