我知道它在许多论坛和博客中都是一个众所周知的主题。我读了很多文章。其中许多都是安静的信息。但对我来说,它似乎需要新的方法来完成这项任务。
我正在寻找在服务器端打印html的解决方案。但在与许多选项合作后,我意识到我们
后来才知道ghostscript(https://stackoverflow.com/a/2600189/1238159)可以用来在服务器端静默打印PDF。
还尝试了水晶报告(但是如果它不支持很多标签,如何动态地将HTML内容传递给它),itextsharp,ssrs,pdfsharp等等,但它们都没有支持许多HTMl标签& W3C标准。所以我在某一时刻结束了生成PDF。只有wkhtmltopdf非常适合将html转换为pdf。它支持每个html标签,不同于我的经验。但印刷PDF对我来说是多年来的问题。
但即使使用GhostScript,我现在也面临着一个问题(使用的是ver 9.05)。使用localhost,我可以完美地使用它。我可以在服务器端打印来自UI的打印机名称。但是IP地址或机器名称无效。我甚至实施了模仿。即使在调用GhostScript时进程被挂起了。
现在我想要明白的是
任何线索或解决方法都可能有助于全球数小时的人们。 :)
非常感谢提前。
此致 Pavan N
使用刘的建议后。能够在命令提示符下执行此操作(意味着cmd.exe在我的帐户下运行)。但我的应用程序将在网络服务下运行。 现在我遇到的问题只是一种ACCESS Denied
呀。最后我能够开始这个过程。并且能够使用我的域凭据在任务管理器下查看我的gswin32c.exe进程。代码如下:
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;
}
}
}
但是这个过程在localhost:5030中完美运行,即从我的visual studio运行时。但使用IP地址或机器名称。它只是挂起并抛出此错误
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() )
答案 0 :(得分:3)
我一直致力于一个正在做这件事的项目。这是一次非常令人沮丧的经历。我找到的最可靠的方法是将我的报告导出为PDF,然后通过Diagnostics.Process使用福昕阅读器(因安全问题而不是Adobe Reader)来打印文档。
可以将打印机名称提供给Foxit Reader命令行参数。
我正在使用的环境是Windows Server 2008 R2 x64上的IIS 7上的ASP.net 3.5。 我也在使用Sql Server Reporting Services。
也许这段代码会帮助你:
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;
}
我的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 "{0}" "{1}"" />
<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>
答案 1 :(得分:1)
对于迟到的帖子感到抱歉。我教过我已经回答了这个问题。 我找到了将html转换为pdf的工作。 我正在使用WKHTMLTOPDF API将html转换为pdf。与许多商业产品相比,它看起来很棒。能够获得彩色/灰度,边距,索引。还有更多。
这是我跟随的链接 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();
和我发送的ghostscript相同,以获得一个漂亮的TIFF文件进行传真。大数据也表现良好。
此致 Pavan N