sme*_*ung 6 .net c# stdin relative-path wkhtmltopdf
我正在使用wkhtmltopdf.exe(版本0.12.0 final)从html文件生成pdf文件,我使用.NET C#
我的问题是只通过在html中指定相对路径来使javascript,样式表和图像工作.现在,如果我使用绝对路径,我可以使用它.但它不适用于相对路径,这使得整个html生成有点复杂.我把我做的事情煮成了下面的例子:
string CMDPATH = @"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe";
string HTML = string.Format(
"<div><img src=\"{0}\" /></div><div><img src=\"{1}\" /></div><div>{2}</div>",
"./sohlogo.png",
"./ACLASS.jpg",
DateTime.Now.ToString());
WriteFile(HTML, "test.html");
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = CMDPATH;
psi.UseShellExecute = false;
psi.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.Arguments = "-q - -";
p = Process.Start(psi);
StreamWriter stdin = p.StandardInput;
stdin.AutoFlush = true;
stdin.Write(HTML);
stdin.Dispose();
MemoryStream pdfstream = new MemoryStream();
CopyStream(p.StandardOutput.BaseStream, pdfstream);
p.StandardOutput.Close();
pdfstream.Position = 0;
WriteFile(pdfstream, "test.pdf");
p.WaitForExit(10000);
int test = p.ExitCode;
p.Dispose();
Run Code Online (Sandbox Code Playgroud)
我尝试过相对路径,例如:"./ sohlogo.png",只需"sohlogo.png",它们都可以通过html文件在浏览器中正确显示.但它们都不适用于pdf文件.错误流中没有数据.
以下命令行的工作方式类似于具有相对路径的魅力:
"c:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe" test.html test.pdf
Run Code Online (Sandbox Code Playgroud)
在这个阶段我真的需要一些输入.所以任何帮助都非常感谢!
仅供参考,WriteFile和CopyStream方法如下所示:
public static void WriteFile(MemoryStream stream, string path)
{
using (FileStream writer = new FileStream(path, FileMode.Create))
{
byte[] bytes = stream.ToArray();
writer.Write(bytes, 0, bytes.Length);
writer.Flush();
}
}
public static void WriteFile(string text, string path)
{
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine(text);
writer.Flush();
}
}
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我对Neo Nguyen的解决方法.
我无法通过相对路径来实现这一点.所以我所做的是一种方法,它使用根路径预先建立所有路径.它解决了我的问题所以也许它会解决你的问题:
/// <summary>
/// Prepends the basedir x in src="x" or href="x" to the input html text
/// </summary>
/// <param name="html">the initial html</param>
/// <param name="basedir">the basedir to prepend</param>
/// <returns>the new html</returns>
public static string MakeRelativePathsAbsolute(string html, string basedir)
{
string pathpattern = "(?:href=[\"']|src=[\"'])(.*?)[\"']";
// SM20140214: tested that both chrome and wkhtmltopdf.exe understands "C:\Dir\..\image.png" and "C:\Dir\.\image.png"
// Path.Combine("C:/
html = Regex.Replace(html, pathpattern, new MatchEvaluator((match) =>
{
string newpath = UrlEncode(Path.Combine(basedir, match.Groups[1].Value));
if (!string.IsNullOrEmpty(match.Groups[1].Value))
{
string result = match.Groups[0].Value.Replace(match.Groups[1].Value, newpath);
return result;
}
else
{
return UrlEncode(match.Groups[0].Value);
}
}));
return html;
}
private static string UrlEncode(string url)
{
url = url.Replace(" ", "%20").Replace("#", "%23");
return url;
}
Run Code Online (Sandbox Code Playgroud)
我尝试了不同的System.Uri.Escape.Sscape***方法,如System.Uri.EscapeDataString().但他们最终对wkhtmltopdf进行了严格的url编码以理解它.由于时间不够,我只是在上面做了快速而又脏的UrlEncode.
快速查看,我认为问题可能出在
psi.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
Run Code Online (Sandbox Code Playgroud)
我认为这就是路径所指向的地方。我假设
"c:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe" test.html test.pdf
Run Code Online (Sandbox Code Playgroud)
工作意味着您的图像按test.html原样在src="mlp.png"内部引用c:\Program Files\wkhtmltopdf\bin\mlp.png,对吗?我认为它有效,因为您的图像文件与 wkhtmltopdf 位于同一文件夹中...因此请尝试将其设置WorkingDirectory为该目录,看看会发生什么。