简体   繁体   English

服务器端的html或pdf打印c#

[英]html or pdf printing on server side c#

I know its a known topic in many forums and blogs. 我知道它在许多论坛和博客中都是一个众所周知的话题。 I read many articles. 我读了很多文章。 And many of them are quiet informative. 其中许多都是安静的信息。 But for me it seems like it demands new approach to achieve this task. 但对我来说,它似乎需要新的方法来完成这项任务。

Am looking for a solution to print a html on server side. 我正在寻找在服务器端打印html的解决方案。 But after working with many options i realised that we 但在与许多选项合作后,我意识到了这一点

  1. cant give printer name or 不能给打印机名称或
  2. its printing html raw content like a txt file 它打印html原始内容,如txt文件

Later came to know about ghostscript ( https://stackoverflow.com/a/2600189/1238159 ) can be used to print a PDF on server side silently. 后来才知道ghostscript( https://stackoverflow.com/a/2600189/1238159 )可以用来在服务器端静默打印PDF。

Also tried with crystal report (but how to pass HTML content to it dynamically eventhough it wont support many tags), itextsharp, ssrs, pdfsharp etc etc but none of them were supporting many of the HTMl tags & W3C standards. 还尝试了水晶报告(但是如果动态地将HTML内容传递给它,尽管它不支持许多标签),itextsharp,ssrs,pdfsharp等等,但它们都没有支持许多HTMl标签和W3C标准。 So i ended at one point to generate PDF. 所以我在某一时刻结束了生成PDF。 Only wkhtmltopdf is perfect for converting html to pdf. 只有wkhtmltopdf非常适合将html转换为pdf。 it supports every html tag unlike anyother as of my experience. 它支持每个html标签,不同于我的经验。 but printing PDf is the question for me from many years. 但打印PDf对我来说是多年来的问题。

But now am facing a problem even with GhostScript (am using ver 9.05). 但即使使用GhostScript,我现在面临着一个问题(使用的是ver 9.05)。 With localhost i can use it perfectly. 使用localhost,我可以完美地使用它。 i can print on server side to what ever printer name coming from UI silently. 我可以在服务器端打印来自UI的打印机名称。 but with the IP address or machine name its not working. 但是IP地址或机器名称无效。 i even implemented Impersonation. 我甚至实施了模仿。 Even though the process gets hanged while calling GhostScript. 即使在调用GhostScript时进程被挂起。

Now what i want to get clear is 现在我想清楚的是

  1. Is it possible to print a html or pdf (actual content) on server side? 是否可以在服务器端打印html或pdf(实际内容)?
  2. Any open source tools are there to achieve this 任何开源工具都可以实现这一目标
  3. printer name I would like to pass dynamically 打印机名称我想动态传递

Any clue or workaround might help many hours of people around the globe. 任何线索或解决方法都可能有助于全球许多小时的人们。 :) :)

Many thanks in advance. 提前谢谢了。

Regards, Pavan N 此致,Pavan N.

After using the suggestion by Lau. 使用刘的建议后。 am able to do it in command prompt (means cmd.exe runs under my account). 能够在命令提示符下执行此操作(意味着cmd.exe在我的帐户下运行)。 but my application will run under network service. 但我的应用程序将在网络服务下运行。 Now am getting a problem just a kind of this ACCESS Denied 现在我遇到的问题就是这种ACCESS被拒绝了

Yeah. 是啊。 Finally i was able to start the process. 最后我能够开始这个过程。 and am able to see my gswin32c.exe process under task manager with my domain credentials. 并且能够使用我的域凭据在任务管理器下查看我的gswin32c.exe进程。 code is as follows: 代码如下:

public bool PrintVSPDF(string ghostScriptPath, int numberOfCopies, string printerName, string pdfFileName)
{
    Logger.AddToLog("printerName", printerName);
    string impersonationUsername = "";
    string impersonationDomain = "";
    string impersonationPWD = "";

    if (ConfigurationManager.AppSettings["UName"] != null)
    {
        impersonationUsername = Encryption.Decrypt(ConfigurationManager.AppSettings["UName"].ToString(), Encryption.DEFAULT_KEY, Encryption.DEFAULT_SEED);
        impersonationDomain = impersonationUsername.Split('\\').Count() > 1 ? impersonationUsername.Split('\\')[0] : "";
        impersonationUsername = impersonationUsername.Split('\\').Count() > 1 ? impersonationUsername.Split('\\')[1] : impersonationUsername.Split('\\')[0];
    }

    if (ConfigurationManager.AppSettings["PD"] != null)
    {
        impersonationPWD = Encryption.Decrypt(ConfigurationManager.AppSettings["PD"].ToString(), Encryption.DEFAULT_KEY, Encryption.DEFAULT_SEED);
    }

    using (Impersonation imp = new Impersonation(impersonationUsername, impersonationDomain, impersonationPWD))
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.Arguments = "-dPrinted -dNoCancel -dNOPAUSE -dBATCH -dNumCopies=" + Convert.ToString(numberOfCopies) + "  -sDEVICE=mswinpr2 -sOutputFile=%printer%\"" + printerName + "\" \"" + pdfFileName + "\" ";
        startInfo.FileName = ghostScriptPath;
        startInfo.UseShellExecute = false;
        startInfo.CreateNoWindow = true;
        //startInfo.RedirectStandardInput = true;
        startInfo.RedirectStandardError = true;
        startInfo.RedirectStandardOutput = true;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.UserName = impersonationUsername;
        startInfo.Domain = impersonationDomain;
        SecureString ss = new SecureString();
        for (int i = 0; i < impersonationPWD.Length; i++)
        {
            ss.AppendChar(impersonationPWD[i]);
        }
        startInfo.Password = ss;
        Process process = null;
        try
        {
            process = Process.Start(startInfo);
            //Logger.AddToLog("Error VS", process.StandardError.ReadToEnd());
            //Logger.AddToLog("Output VS", process.StandardOutput.ReadToEnd());
            //Logger.AddToLog(process.StartInfo.Arguments.ToString(), "VS Print Arguments");
            //Console.WriteLine(process.StandardError.ReadToEnd() + process.StandardOutput.ReadToEnd());
            //Logger.AddToLog(process.StartInfo.FileName.ToString(), "VS Print file name");
            process.WaitForExit(30000);
            if (process.HasExited == false) 
                process.Kill();
            int exitcode = process.ExitCode;
            process.Close();
            return exitcode == 0;
        }
        catch (Exception ex)
        {
            Logger.AddToLog(ex);
            return false;
        }
    }
}

But the process is working perfectly in localhost:5030 ie., while running from my visual studio. 但是这个过程在localhost:5030中完美运行,即从我的visual studio运行时。 but with IP address or machine name. 但使用IP地址或机器名称。 it just hangs and throws this error 它只是挂起并抛出此错误

Same thing is happening for adobe reader, foxit, etc etc. adobe reader,foxit等正在发生同样的事情。

( Process must exit before requested information can be determined. :    at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.get_ExitCode() )

I have been working on a project that is doing just this. 我一直致力于一个正在做这件事的项目。 It has been a very frustrating experience. 这是一次非常令人沮丧的经历。 The most reliable method I have found is to export my reports to PDF and then use Foxit Reader (NOT Adobe Reader due to security problems) via Diagnostics.Process to print the document. 我找到的最可靠的方法是将我的报告导出为PDF,然后通过Diagnostics.Process使用福昕阅读器(因安全问题而不是Adobe Reader)来打印文档。

The printer name can be supplied to the Foxit Reader command line args. 打印机名称可以提供给Foxit Reader命令行参数。

The environment I am working with is ASP.net 3.5 on IIS 7 on Windows Server 2008 R2 x64. 我正在使用的环境是Windows Server 2008 R2 x64上的IIS 7上的ASP.net 3.5。 I am also using Sql Server Reporting Services. 我也在使用Sql Server Reporting Services。

Maybe this code will help you out: 也许这段代码会帮助你:

    public FileContentResult GetPOReport(DataTable reportData, int poNumber, string copies, out string fileName, out string downloadPath)
    {
        fileName = "PO_" + poNumber.ToString().Trim() + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".pdf";
        downloadPath = "/Generated/" + fileName;

        var outputFiles = new Dictionary<string, string>
                              {
                                  {"", Server.MapPath("~" + downloadPath)}
                              };

        if (!string.IsNullOrWhiteSpace(copies))
        {
            var copyList = copies.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var temp in copyList)
                outputFiles.Add(temp, Server.MapPath("~" + "/Generated/" + temp.Trim() + ".pdf"));
        }

        FileContentResult returnFile = null;

        foreach (var outputFile in outputFiles)
        {
            var file = WriteReportToDisk(reportData, outputFile.Value, outputFile.Key);

            if (file == null)
                continue;

            if (string.IsNullOrWhiteSpace(outputFile.Key))
                returnFile = file;
            else
                PrintReport(outputFile.Value);
        }

        return returnFile;
    }

    public void PrintReport(string filePath)
    {
        try
        {
            if (!ConfigurationManager.AppSettings.AllKeys.Contains("AdobeReaderPath") ||
                !ConfigurationManager.AppSettings.AllKeys.Contains("AdobePrintParameters") ||
                !ConfigurationManager.AppSettings.AllKeys.Contains("PrinterName"))
                return;

            var adobeReaderPath = ConfigurationManager.AppSettings["AdobeReaderPath"].Trim();
            var adobePrintParameters = ConfigurationManager.AppSettings["AdobePrintParameters"].Trim();
            var printerName = ConfigurationManager.AppSettings["PrinterName"].Trim();
            var printProcessDomain = ConfigurationManager.AppSettings["PrintProcessDomain"].Trim();
            var printProcessUserName = ConfigurationManager.AppSettings["PrintProcessUserName"].Trim();
            var printProcessPassword = ConfigurationManager.AppSettings["PrintProcessPassword"].Trim();

            var userPrinter = Entities.UserPrinters.FirstOrDefault(p => p.UserName == User.Identity.Name);

            if (userPrinter != null)
                printerName = userPrinter.PrinterName.Trim();

            using (var process = new Process
            {
                StartInfo =
                    new ProcessStartInfo(
                    adobeReaderPath,
                    string.Format(adobePrintParameters, filePath, printerName)
                    )
            })
            {
                if (!string.IsNullOrWhiteSpace(printProcessUserName))
                {
                    if (!string.IsNullOrWhiteSpace(printProcessDomain))
                        process.StartInfo.Domain = printProcessDomain;

                    process.StartInfo.UserName = printProcessUserName;

                    var securePassword = new SecureString();

                    foreach (var passwordCharacter in printProcessPassword)
                        securePassword.AppendChar(passwordCharacter);

                    process.StartInfo.Password = securePassword;

                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.CreateNoWindow = true;

                    process.StartInfo.LoadUserProfile = true;
                }

                process.Start();

                process.WaitForExit(30000);
            }
        }
        catch (Exception exception)
        {
            EventLog.WriteEntry("PO Suggestion Viewer", string.Format("PO Suggestion Viewer Error:\n{0}", exception.Message));
            throw;
        }
    }

    public FileContentResult WriteReportToDisk(DataTable reportData, string filePath, string copy)
    {
        var webReport = new WebReport()
        {
            ExportFileName = "PO Report",
            ReportPath = Server.MapPath("~/Reports/PurchaseOrderReport.rdlc")
        };

        if (!string.IsNullOrWhiteSpace(copy))
            webReport.ReportParameters.Add(new ReportParameter("Copy", copy));

        if ((User != null) && (User.Identity != null) && (User.Identity.Name != null))
            webReport.ReportParameters.Add(new ReportParameter("User", User.Identity.Name));

        webReport.ReportDataSources.Add(new ReportDataSource("ReportData", reportData));

        var report = webReport.GetReport();

        Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.{1}", webReport.ExportFileName, webReport.FileNameExtension));
        Response.ContentType = "application/pdf";

        var file = File(report, webReport.MimeType, "POReport");

        System.IO.File.WriteAllBytes(filePath, file.FileContents);

        return file;
    }

My web.config contains: 我的web.config包含:

<appSettings>
    <add key="webpages:Version" value="1.0.0.0" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="AdobeReaderPath" value="C:\Program Files (x86)\Foxit Software\Foxit Reader\Foxit Re-ader.exe" />
    <add key="AdobePrintParameters" value="-t &quot;{0}&quot; &quot;{1}&quot;" />
    <add key="PrinterName" value="HP_Office" />
    <add key="PrintProcessDomain" value="DOMAIN_NAME" />
    <add key="PrintProcessUserName" value="DOMAIN_USER" />
    <add key="PrintProcessPassword" value="DOMAIN_PASSWORD" />
</appSettings>

sorry for the late posting. 对于迟到的帖子感到抱歉。 i taught i already answered this Q. I found a work around to convert html to pdf. 我教过我已经回答了这个问题。我找到了将html转换成pdf的工作。 am using WKHTMLTOPDF API to convert the html to pdf. 我正在使用WKHTMLTOPDF API将html转换为pdf。 and it looks awesome compared to many commercial products out there. 与许多商业产品相比,它看起来很棒。 am able to get coloured/greyscale, margins, indexing. 能够获得彩色/灰度,边距,索引。 and many more. 还有很多。

here is the link i followed http://code.google.com/p/wkhtmltopdf/ 这是我跟随的链接http://code.google.com/p/wkhtmltopdf/

ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + @"\bin\wkhtmltopdf.exe";
pdfFile = localReportPath + "\\Reports\\Savedfiles\\" + filename + ".pdf";
//Ref: http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html
startInfo.Arguments = " --minimum-font-size 16 --margin-left 10mm --margin-right 10mm --zoom 3 " + htmlFile + " " + pdfFile;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(startInfo);
p.WaitForExit();
p.Dispose();
p.Close();

and the same i sent for ghostscript to get an beautiful TIFF file for faxing. 和我发送的ghostscript相同,以获得一个美丽的TIFF文件进行传真。 performance is good with huge data also. 大数据也表现良好。

Regards, Pavan N 此致,Pavan N.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM