Rotativa.aspnetcore 中的构建文件错误

BuildFile Error In Rotativa.aspnetcore

在 asp.net 核心 2.1 应用程序中使用旋转将视图转换为 pdf 时出现错误

Value cannot be null. Parameter name: path1

下面是我的代码

var rpt = new ViewAsPdf();
            //rptLandscape.Model = Model;
            rpt.PageOrientation = Rotativa.AspNetCore.Options.Orientation.Landscape;
            rpt.PageSize = Rotativa.AspNetCore.Options.Size.A4;
            rpt.ViewName = "Test";
            byte[] arr = await rpt.BuildFile(actionContextAccessor.ActionContext);
            System.IO.File.WriteAllBytes(Path.Combine(env.WebRootPath, "PDFStorage", "File.pdf"), arr);

虽然它 returns 网页作为 pdf 成功,但我想将它存储在一个文件夹中。 此错误的可能原因是什么? ,我已经检查了所有,它甚至不包含名称 name1

的 属性

更新 1:错误不在 Path.Combine() 中,错误在它之前的行中。

byte[] arr = await rpt.BuildFile(actionContextAccessor.ActionContext);

Path.Combine 如果其中一个输入字符串是 null.

则抛出 ArgumentNullException

env.WebRootPathnull,确保它已用值初始化。


SourcePath.Combine:

public static String Combine(String path1, String path2, String path3) {
    if (path1 == null || path2 == null || path3 == null)
        throw new ArgumentNullException((path1 == null) ? "path1" : (path2 == null) ? "path2" : "path3");
    Contract.EndContractBlock();
    CheckInvalidPathChars(path1);
    CheckInvalidPathChars(path2);
    CheckInvalidPathChars(path3);

    return CombineNoChecks(CombineNoChecks(path1, path2), path3);
}

精简版

您需要调用 RotativaConfiguration.Setup(env); in Startup.cs 下载并部署另一个工具来完成实际的转换工作。您可能应该找一个不同的库。

长版

没有实际的异常及其调用堆栈,只能猜测,或检查 the source code 并尝试猜测可能出现的问题。

BuildFile 的源代码是:

   public async Task<byte[]> BuildFile(ActionContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        //if (this.WkhtmlPath == string.Empty)
        //    this.WkhtmlPath = context.HttpContext.Server.MapPath("~/Rotativa");

        this.WkhtmlPath = RotativaConfiguration.RotativaPath;

        var fileContent = await CallTheDriver(context);

        if (string.IsNullOrEmpty(this.SaveOnServerPath) == false)
        {
            File.WriteAllBytes(this.SaveOnServerPath, fileContent);
        }

        return fileContent;
    }

WriteAllBytes 不可能是罪魁祸首。它 确实 RotativaConfiguration.RotativaPath 设置中设置了 WkhtmlPath 属性。在 CallTheDriver() 内部的调用之后显示该库只是调用一个带有一些开关的可执行文件来转换 PDF 文件。

执行exe的actual call,从ViewAsPdf.cs追踪到WkhtmlDriver.cs是:

        var proc = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = Path.Combine(wkhtmlPath, wkhtmlExe),
                Arguments = switches,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                RedirectStandardInput = true,
                WorkingDirectory = wkhtmlPath,
                CreateNoWindow = true
            }
        };
        proc.Start();

如果 wkhtmlPath 为空,您将得到一个空参数异常。所有这些调用都会出现在异常的调用堆栈中。

解决方法是确保 RotativaConfiguration.RotativaPath 属性 设置正确。回购本身 explains that :

Basic configuration done in Startup.cs:

RotativaConfiguration.Setup(env);

Make sure you have a folder with the wkhtmltopdf.exe file accessible by the process running the web app. By default it searches in a folder named "Rotativa" in the root of the web app. If you need to change that use the optional parameter to the Setup call RotativaConfiguration.Setup(env, "path/relative/to/root")

顺便说一句,该库的作用是,运行 web 应用程序中的单独可执行文件 是一个非常非常糟糕的主意:

  1. 失去了可伸缩性。 运行 每个请求的单独可执行文件 非常 昂贵并且很容易淹没繁忙的服务器。这就是生产服务器不以这种方式工作的原因。如果进程挂起,请求将被处理。您最终可能会遇到孤立的进程。
  2. 其次,它需要更高的权限 - 网络应用程序的帐户必须能够执行任意可执行文件,它应该被允许这样做。

最后,忘掉跨平台部署吧。可执行文件名称是 hard-coded to "wkhtmltopdf.exe", even though the https://wkhtmltopdf.org/ 网站提供所有操作系统的版本。

顺便说一下,该工具本身提供了一个 C 库供其他应用程序使用