Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调用wkhtmltopdf从HTML生成PDF_Html_Asp.net_Pdf_Pdf Generation_Wkhtmltopdf - Fatal编程技术网

调用wkhtmltopdf从HTML生成PDF

调用wkhtmltopdf从HTML生成PDF,html,asp.net,pdf,pdf-generation,wkhtmltopdf,Html,Asp.net,Pdf,Pdf Generation,Wkhtmltopdf,我正在尝试从HTML文件创建PDF文件。环顾四周后,我发现:要完美。我需要从ASP.NET服务器调用此.exe。我试图: Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.FileName = HttpContext.Current.Server.MapPath("wkhtmltopdf.exe"); p.StartInfo.Arguments = "TestPD

我正在尝试从HTML文件创建PDF文件。环顾四周后,我发现:要完美。我需要从ASP.NET服务器调用此.exe。我试图:

    Process p = new Process();
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.FileName = HttpContext.Current.Server.MapPath("wkhtmltopdf.exe");
    p.StartInfo.Arguments = "TestPDF.htm TestPDF.pdf";
    p.Start();
    p.WaitForExit();
没有在服务器上成功创建任何文件。谁能给我一个指向正确方向的指针吗?我将wkhtmltopfd.exe文件放在站点的顶级目录中。还有其他地方应该举行吗



编辑:如果有更好的解决方案可以从html动态创建pdf文件,请告诉我。

ASP.Net进程可能没有对该目录的写入权限

试着告诉它写入
%TEMP%
,看看它是否有效


另外,让您的ASP.Net页面回显进程的stdout和stderr,并检查错误消息。

这通常是一个坏主意的原因有很多。如果发生崩溃,您将如何控制生成但最终仍保留在内存中的可执行文件?如果拒绝服务攻击,或者如果有恶意内容进入TestPDF.htm,该怎么办

我的理解是ASP.NET用户帐户将无权在本地登录。它还需要具有正确的文件权限才能访问可执行文件和写入文件系统。您需要编辑本地安全策略,并让ASP.NET用户帐户(可能是ASP.NET)在本地登录(默认情况下,它可能位于拒绝列表中)。然后,您需要编辑NTFS文件系统上其他文件的权限。如果您处于共享主机环境中,则可能无法应用所需的配置


使用这样的外部可执行文件的最佳方法是从ASP.NET代码中将作业排队,并让某种服务监视队列。如果你这样做,你会保护自己不受各种坏事的影响。在我看来,更改用户帐户的维护问题不值得付出努力,虽然设置服务或计划作业是一件痛苦的事情,但这只是一个更好的设计。ASP.NET页面应轮询输出的结果队列,您可以向用户提供等待页面。这在大多数情况下是可以接受的。

更新:
下面我的答案是,在磁盘上创建pdf文件。然后我将该文件作为下载流式传输到用户浏览器。考虑使用下面的“像”的答案来获得WKHTML2PDF,以输出到流,然后直接发送给用户——这将绕过文件权限等问题。

我的原始答案:
确保您已经为PDF指定了一个输出路径,该路径可由服务器上运行的IIS的ASP.NET进程写入(我认为通常是网络服务)

我的看起来是这样的(而且很有效):

//
///使用开源工具wkhtml2pdf将给定URL处的Html页面转换为PDF文件
/// 
/// 
/// 
/// 
公共静态bool HtmlToPdf(字符串Url、字符串输出文件名)
{
//汇编目标PDF文件名
字符串文件名=ConfigurationManager.AppSettings[“ExportFilePath”]+“\\”+outputFilename+“.pdf”;
//获取标题的项目编号
项目=新项目(int.Parse(outputFilename));
var p=新系统.Diagnostics.Process();
p、 StartInfo.FileName=ConfigurationManager.AppSettings[“HtmlToPdfExePath”];
字符串开关=“--打印介质类型”;
开关+=“--上边距4mm--下边距4mm--右边距0mm--左边距0mm”;
开关+=“--页面大小A4”;
开关+=“--无背景”;
开关+=“--重定向延迟100”;
p、 StartInfo.Arguments=switches+“”+Url+“”+filename;
p、 StartInfo.UseShellExecute=false;//需要为false才能重定向输出
p、 StartInfo.RedirectStandardOutput=true;
p、 StartInfo.RedirectStandardError=true;
p、 StartInfo.RedirectStandardInput=true;//重定向全部3,因为它应该是全部3或无
p、 StartInfo.WorkingDirectory=StripFilenameFromFullPath(p.StartInfo.FileName);
p、 Start();
//阅读这里的输出。。。
字符串输出=p.StandardOutput.ReadToEnd();
//…然后等待n毫秒以退出(与退出后一样,它无法读取输出)
p、 WaitForExit(60000);
//读取退出代码,关闭进程
int returnCode=p.ExitCode;
p、 Close();
//如果为0或2,则有效(不确定其他值,我需要更好的方法来确认)
返回(返回代码==0 | |返回代码==2);
}
使用系统;
使用系统诊断;
使用System.Web;
公共部分类pdftest:System.Web.UI.Page
{
受保护的无效页面加载(对象发送方、事件参数e)
{
}
私有无效fn_测试()
{
尝试
{
字符串url=HttpContext.Current.Request.url.AbsoluteUri;
Response.Write(url);
ProcessStartInfo startInfo=新的ProcessStartInfo();
startInfo.FileName=
@“C:\PROGRA~1\WKHTML~1\wkhtmltopf.exe”;/“wkhtmltopf.exe”;
startInfo.Arguments=url+@“C:\test”
+Guid.NewGuid().ToString()+“.pdf”;
进程启动(startInfo);
}
捕获(例外情况除外)
{
字符串xx=ex.Message.ToString();
响应。写入(“
”+xx); } } 受保护的无效btn\u测试\u单击(对象发送方,事件参数e) { fn_检验(); } }
您可以通过指定“-”作为输出文件,告诉wkhtmltopdf将其输出发送到sout。
然后,您可以将进程的输出读取到响应流中,避免写入文件系统时出现权限问题。

我在尝试将msmq与windows服务一起使用时也遇到了同样的问题,但由于某些原因,速度非常慢。(过程部分)

这就是最终成功的原因:

private void DoDownload()
{
    var url = Request.Url.GetLeftPart(UriPartial.Authority) + "/CPCDownload.aspx?IsPDF=False?UserID=" + this.CurrentUser.UserID.ToString();
    var file = WKHtmlToPdf(url);
    if (file != null)
    {
        Response.ContentType = "Application/pdf";
        Response.BinaryWrite(file);
        Response.End();
    }
}

public byte[] WKHtmlToPdf(string url)
{
    var fileName = " - ";
    var wkhtmlDir = "C:\\Program Files\\wkhtmltopdf\\";
    var wkhtml = "C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe";
    var p = new Process();

    p.StartInfo.CreateNoWindow = true;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.FileName = wkhtml;
    p.StartInfo.WorkingDirectory = wkhtmlDir;

    string switches = "";
    switches += "--print-media-type ";
    switches += "--margin-top 10mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
    switches += "--page-size Letter ";
    p.StartInfo.Arguments = switches + " " + url + " " + fileName;
    p.Start();

    //read output
    byte[] buffer = new byte[32768];
    byte[] file;
    using(var ms = new MemoryStream())
    {
        while(true)
        {
            int read =  p.StandardOutput.BaseStream.Read(buffer, 0,buffer.Length);

            if(read <=0)
            {
                break;
            }
            ms.Write(buffer, 0, read);
        }
        file = ms.ToArray();
    }

    // wait or exit
    p.WaitForExit(60000);

    // read the exit code, close process
    int returnCode = p.ExitCode;
    p.Close();

    return returnCode == 0 ? file : null;
}
private void DoDownload()
{
var url=Request.url.GetLeftPart(UriPartial.Authority)+“/CPCDownload.aspx?IsPDF=False?UserID=“+this.CurrentUser.UserID.ToString();
变量文件=
using System;
using System.Diagnostics;
using System.Web;

public partial class pdftest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    private void fn_test()
    {
        try
        {
            string url = HttpContext.Current.Request.Url.AbsoluteUri;
            Response.Write(url);
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.FileName = 
                @"C:\PROGRA~1\WKHTML~1\wkhtmltopdf.exe";//"wkhtmltopdf.exe";
            startInfo.Arguments = url + @" C:\test"
                 + Guid.NewGuid().ToString() + ".pdf";
            Process.Start(startInfo);
        }
        catch (Exception ex)
        {
            string xx = ex.Message.ToString();
            Response.Write("<br>" + xx);
        }
    }
    protected void btn_test_Click(object sender, EventArgs e)
    {
        fn_test();
    }
}
private void DoDownload()
{
    var url = Request.Url.GetLeftPart(UriPartial.Authority) + "/CPCDownload.aspx?IsPDF=False?UserID=" + this.CurrentUser.UserID.ToString();
    var file = WKHtmlToPdf(url);
    if (file != null)
    {
        Response.ContentType = "Application/pdf";
        Response.BinaryWrite(file);
        Response.End();
    }
}

public byte[] WKHtmlToPdf(string url)
{
    var fileName = " - ";
    var wkhtmlDir = "C:\\Program Files\\wkhtmltopdf\\";
    var wkhtml = "C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe";
    var p = new Process();

    p.StartInfo.CreateNoWindow = true;
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.RedirectStandardError = true;
    p.StartInfo.RedirectStandardInput = true;
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.FileName = wkhtml;
    p.StartInfo.WorkingDirectory = wkhtmlDir;

    string switches = "";
    switches += "--print-media-type ";
    switches += "--margin-top 10mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
    switches += "--page-size Letter ";
    p.StartInfo.Arguments = switches + " " + url + " " + fileName;
    p.Start();

    //read output
    byte[] buffer = new byte[32768];
    byte[] file;
    using(var ms = new MemoryStream())
    {
        while(true)
        {
            int read =  p.StandardOutput.BaseStream.Read(buffer, 0,buffer.Length);

            if(read <=0)
            {
                break;
            }
            ms.Write(buffer, 0, read);
        }
        file = ms.ToArray();
    }

    // wait or exit
    p.WaitForExit(60000);

    // read the exit code, close process
    int returnCode = p.ExitCode;
    p.Close();

    return returnCode == 0 ? file : null;
}
var pdfData = HtmlToXConverter.ConvertToPdf("<h1>SOO COOL!</h1>");
public async Task<byte[]> GeneratePdf(string html, string additionalArgs)
{
    ProcessStartInfo psi = new ProcessStartInfo
    {
        FileName = @"C:\Program Files\wkhtmltopdf\wkhtmltopdf.exe",
        UseShellExecute = false,
        CreateNoWindow = true,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        Arguments = "-q -n " + additionalArgs + " - -";
    };

    using (var p = Process.Start(psi))
    using (var pdfSream = new MemoryStream())
    using (var utf8Writer = new StreamWriter(p.StandardInput.BaseStream, 
                                             Encoding.UTF8))
    {
        await utf8Writer.WriteAsync(html);
        utf8Writer.Close();
        var tStdOut = p.StandardOutput.BaseStream.CopyToAsync(pdfSream);
        var tStdError = p.StandardError.ReadToEndAsync();

        await tStandardOutput;
        string errors = await tStandardError;

        if (!string.IsNullOrEmpty(errors)) { /* deal/log with errors */ }

        return pdfSream.ToArray();
    }
}