c# - 具有重定向输入/输出流的 HTML 中的 wkhtmltopdf 相对路径将不起作用

标签 c# .net stdin relative-path wkhtmltopdf

我正在使用 wkhtmltopdf.exe(最终版本 0.12.0)从 html 文件生成 pdf 文件,我使用 .NET C# 执行此操作

我的问题是让 javascript、样式表和图像仅通过在 html 中指定相对路径来工作。现在,如果我使用绝对路径,我可以正常工作。但它不适用于相对路径,这使得整个 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();

我已经尝试过相对路径,例如:“./sohlogo.png”和简单的“sohlogo.png”都可以通过 html 文件在浏览器中正确显示。但它们都不能在 pdf 文件中工作。错误流中没有数据。

下面的命令行与相对路径一起工作就像一个魅力:

"c:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe" test.html test.pdf

在这个阶段我真的需要一些意见。所以非常感谢任何帮助!

仅供引用,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);
    }
}

编辑:我对 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;
}

我尝试了不同的 System.Uri.Escape*** 方法,例如 System.Uri.EscapeDataString()。但他们最终对 wkhtmltopdf 进行了严格的 url 编码以理解它。由于时间不够,我只是做了上面快速而肮脏的 UrlEncode。

最佳答案

根据 official docs of the command line ,有一个名为 --cache-dir 的选项。

似乎他们指的是工作目录。 我使用它并且它适用于 v0.12.3

wkhtmltopdf /my/path/to/index.html test.pdf --cache-dir /my/path/to

关于c# - 具有重定向输入/输出流的 HTML 中的 wkhtmltopdf 相对路径将不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21775572/

相关文章:

c# - API架构

c# - 我可以在 Windows 8 操作系统上使用 C# 在 VS2010 上使用直接声音吗?

C#:是否应该将 ""分配给字符串以使其为空?

android - 如何创建多平台本地化解决方案?

c# - 有没有一种简单的方法可以让dynamic/ExpandoObject返回字符串而不是对象?

C 通过 stdin 读取文件读取随机符号

python - Argparse 和 ArgumentDefaultsHelpFormatter。选择 sys.stdin/stdout 作为默认值时的默认值格式

c# - 有没有办法查看 System.Net.Mail 是否有效

c# - 我如何将数组从 .cs 文件传递​​到 .aspx

c - 输入字符串后刷新标准输入,以随后输入下一个字符