.net wkhtmltopdf HTML中的相对路径与重定向的输入/输出流不起作用

mwyxok5s  于 2023-03-20  发布在  .NET
关注(0)|答案(3)|浏览(180)

我使用wkhtmltopdf.exe(最终版本0.12.0)从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();

我尝试过如下相对路径:“./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。

ryhaxcpt

ryhaxcpt1#

对于official docs of the command line,有一个名为--cache-dir的选项。
看起来他们指的是工作目录。我使用它,它与v0. 12. 3一起工作

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

qv7cva1a2#

很快的,我想问题可能在于

psi.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;

我想路径就是指向那里的。我假设

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

工作意味着你的图片在test.html中引用为src="mlp.png"是在c:\Program Files\wkhtmltopdf\bin\mlp.png中,对吗?我认为它工作是因为你的图片文件和wkhtmltopdf在同一个文件夹中...所以试着把WorkingDirectory设置到那个目录,看看会发生什么。

x6492ojm

x6492ojm3#

我使用的是0.12.3版本的wkthmltopdf,在这里你可以使用相对路径,就我所知,它们是相对于源文件的位置。

/documentroot/tmp/myfile.html

你的资产大概是

/documentroot/assets/logo.png

那么链接应该与

"../assets/logo.png"

相关问题