为什么此PhantomJS进程导致“目录<x>不存在”。错误?

婚约

这是我的第一篇文章,如果问题需要更改,我们深表歉意。我已经尽力解决了这个问题,但是这里有很多组件,所以这篇文章相当庞大...

我们的ASP.NET MVC网站被部署为Azure上的应用程序服务。我正在使用API​​控制器方法来生成同一站点上存在的页面的PDF。为此,控制器创建一个PhantomJS进程,等待成功,然后返回其创建的文件的内容。一切正常,但是此后站点上的多个视图会产生如下错误:

“ /”应用程序中的服务器错误。

目录“ D:\ home \ site \ wwwroot \ Views \ Location”不存在。无法开始监视文件更改。

说明: 执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其在代码中起源的更多信息。

异常详细信息: System.Web.HttpException:目录'D:\ home \ site \ wwwroot \ Views \ Location'不存在。无法开始监视文件更改。

一段时间后,错误发生变化:

“ /”应用程序中的服务器错误。

找不到视图“ LocationList”或其主视图,或者没有视图引擎支持搜索到的位置。搜索了以下位置:
〜/ Views / Location / LocationList.aspx〜
/ Views / Location / LocationList.ascx〜
/ Views / Shared / LocationList.aspx〜
/ Views / Shared / LocationList.ascx〜
/ Views / Location / LocationList。 cshtml〜
/ Views / Location / LocationList.vbhtml〜
/ Views / Shared / LocationList.cshtml〜
/ Views / Shared / LocationList.vbhtml

说明: 执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其在代码中起源的更多信息。

异常详细信息: System.InvalidOperationException:找不到视图“ LocationList”或其主视图,或者没有视图引擎支持搜索到的位置。搜索了以下位置:
〜/ Views / Location / LocationList.aspx〜
/ Views / Location / LocationList.ascx〜
/ Views / Shared / LocationList.aspx〜
/ Views / Shared / LocationList.ascx〜
/ Views / Location / LocationList。 cshtml〜
/ Views / Location / LocationList.vbhtml〜
/ Views / Shared / LocationList.cshtml
〜/ Views / Shared / LocationList.vbhtml

这仅适用于尚未编译的视图或以前未访问的任何其他文件。修复它的唯一方法是手动停止并启动Web应用程序。我可以确认并非所有进程都发生这种情况(运行“ echo.exe”而不是“ phantomjs.exe”不会导致行为中断)。

我浏览了所有我能想到的日志,没有发现任何异常。我最好的猜测是某个过程被强制或意外终止,但是关于什么以及为什么,我毫无头绪。也许有一些我不知道的重要日志?

这是相关的C#代码:

private static async Task<int> ExecuteSimpleAsync(string workingDir, double? timeout,
    string command, params string[] parameters)
{
    var paramStr = string.Join(" ", parameters.Select(x => x == null ? "" : $"\"{x}\"").ToList());
    var processInfo = new ProcessStartInfo(command, paramStr) {
        WorkingDirectory = workingDir,
        UseShellExecute  = false,                    
        CreateNoWindow   = true,
    };

    Process process = null;
    int exitCode = -1;
    using (process = new Process() { StartInfo = processInfo }) {
        process.Start();
        await process.WaitForExitAsync(timeout); // simple extension function to check for 'Process.HasExited' periodically
        exitCode = process.ExitCode;
    }
    return exitCode;
}


private static async Task<byte[]> GetFileContents(string filePath) {
    byte[] bytes = null;
    using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read)) {
        bytes = new byte[file.Length];
        await file.ReadAsync(bytes, 0, (int) file.Length);
    }
    return bytes;
}


public static async Task<byte[]> RenderPdfAsync(
    string cookiesB64, string localUrl, string baseFilename, double? timeout = 60)
{
    ....

    // filesPath:  (directory for temporary output)
    // timeout:    60.000 (60 seconds)
    // PhantomJSExePath: (absolute path containing 'phantomjs.exe')
    // scriptFile: "rasterize_simple.js"
    // requestUrl: "TestReport/ForUserAndTestPdf/1002/10"
    // outputFile: "phantomjs-output-<timestamp>.pdf"
    // cookiesB64: (base64-encoded authentication cookies passed to request in PhantomJS)

    var exitCode = await ExecuteSimpleAsync(filesPath, timeout, PhantomJSExePath + @"\phantomjs.exe",
    scriptFile, requestUrl, outputFile, cookiesB64);
    if (exitCode != 0)
        return null;
    return await GetFileContents(outputFile);
}


[Authorize]
[HttpGet]
[Route("TestReport/ForUserAndTestPdf/{userId}/{testId}")]
public async Task<HttpResponseMessage> ForUserAndTestPdfAsync(int userId, int testId) {
    // produce a slightly-modified version of the current URL:
    //    /TestReport/ForUserAndTest/<userid>/<testid>
    // => /TestReport/ForUserAndTestPdf/<userid>/<testid>?print=true
    var url = Request.RequestUri.GetLocalPathWithParams("print=true").Replace("ForUserAndTest", "ForUserAndTestPdf");

    // get the cookies used in the current request and convert to a base64-encoded JSON object
    var cookiesB64 = Request.GetCookiesJsonB64();
    var bytes = await PhantomJSHelpers.RenderPdfAsync(cookiesB64, url, "phantomjs-output", 60);

    var message = new HttpResponseMessage(HttpStatusCode.OK);
    message.Content = new StreamContent(new MemoryStream(bytes));
    message.Content.Headers.ContentLength = bytes.Length;
    message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
    return message;
}

这是PhantomJS使用的“ rasterize_simple.js”脚本的相关部分,没有设置页面大小,Cookie等:

page.open(address, function(status) {
    page.render(outputFilename);
    phantom.exit(0);
});

所有这些的预期结果是生成的PDF文件,并且此API方法(带有不同参数)的所有后续调用均可以正常工作。但是,副作用是一个完全损坏的部位:(

在这里的任何帮助将不胜感激!

彼得潘

恐怕您的ASP.NET应用程序的功能无法在Azure WebApp中正常运行,例如派生一个进程来运行PhantomJS并生成PDF文件,因为存在很多限制,不能执行这些操作,请参阅到Kudu Wiki页面Azure Web App sandbox了解更多信息。

我认为您有一些限制。

  1. 从HTML生成PDF有多个库可用于将HTML转换为PDF。许多Windows / .NET特定版本使用IE API,因此广泛使用User32 / GDI32。这些API在沙盒中被很大程度上阻止(无论计划如何),因此这些框架在沙盒中不起作用。

  2. 不支持的框架这里列出了由于上述一个或多个限制而无法使用的框架和方案。可以想象,随着沙盒的发展,将来会支持某些功能。

    由于上述限制,PDF生成器失败:

    Syncfusion Siberix Spire.PDF支持以下PDF生成器:

    SQL Reporting Framework:要求网站在Basic或更高版本上运行(请注意,当前该网站无法在Consumptions模式下的Functions应用程序中运行)EVOPDF:请参阅http://www.evopdf.com/azure-html-to-pdf-converter .aspx用于供应商解决方案Telerik报告:要求站点在Basic或更高版本中运行。更多信息,请访问Rotativa / wkhtmltopdf:要求该网站以Basic或更高版本运行。NReco PdfGenerator(wkhtmltopdf):需要订阅计划基本或更高版本基于wkhtmltopdf或phantomjs的所有PDF生成器的已知问题:由于沙箱GDI API的限制(即使在VM-基于Azure应用计划(基本或更高版本)。

    不支持的其他方案:

    PhantomJS / Selenium:尝试连接到本地地址,也使用GDI +。

    有些框架没有充分利用User32 / GDI32(例如,wkhtmltopdf),并且我们正在以与启用SQL报告相同的方式在Basic +中启用它们。

  3. 本地地址请求连接尝试到本地地址(例如localhost,127.0.0.1)和计算机自己的IP将失败,除非同一沙箱中的另一个进程在目标端口上创建了侦听套接字。

解决方案是将应用程序部署在Azure VM而非WebApp上。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

PIP安装“错误:包目录'X'不存在”

PSQL:“错误:列 x 不存在”

不存在的目录上的错误500

X0在目录中不存在

javac错误:“导入x”处的“包x不存在”

错误类型“ XX”中不存在类型“ X”

此Azure搜索索引错误是什么意思?“类型'search.documentFields'上不存在属性'x'...”

不断获取文件不存在错误(即使存在目录)

Django视图导致Psycopg2光标不存在/不存在错误

“ X”参数不存在

为什么该程序不存在段错误?

使用“will leave”时,为什么会出现“此框架中不存在名称为'$x'的词法”?

为什么在某些页面上不存在HttpHeader X-Original-URL?

为什么Seaborn会继续在x轴上绘制不存在的范围值?

删除链表中不存在的节点导致分段错误

Autodesk Forge API:“此帐户不存在。” 错误

简单测试输出-CMake错误:源目录不存在

Ansible模板-目标目录不存在错误

如果目录不存在,则 Firebase 错误消息

“插槽不存在”错误消息是什么意思?

为什么不存在<<<?

为什么我的程序返回一个错误,指出文件不存在时它不存在?

“ assets:install”命令失败,并显示错误“目标目录“ web”不存在”,为什么?

为什么bash重定向在nohup下返回错误(“目录不存在”)

目录不存在,但是存在,但是不存在

此集合实例laravel关系上不存在属性[X]

FileWriter不存在目录

名称不存在或目录

工作目录不存在