pdf - 我正在使用 Rotativa 工具来显示 pdf。它在本地主机上运行良好,但在 Azure 平台上不起作用

标签 pdf azure model-view-controller rotativa

我正在使用Rotativa工具来显示PDF。它在localhost上工作正常,但在Azure平台上不起作用。

下面是我的代码...

public ActionResult GeneratePDF(int id = 0)
    {
        ReportTransactionData reporttransactiondata = db.ReportTransactionDatas.Find(id);
        var viewFileToPrint = @"~/Views/ReportTranData/PDFReport.cshtml";
        //var oRotativaPDF = new Rotativa.ViewAsPdf();
        var oRotativaPDF = new Rotativa.PartialViewAsPdf();
        try
        {
            if (reporttransactiondata == null)
            {
                return HttpNotFound();
            }
            else
            {
                // Populate reporttransactiondata with Verfier Name...TO BE IMPLEMENTED LATER...
                //reporttransactiondata.VerifierName = GetVerifierNameByID(reporttransactiondata.VerifierID);
            }

            // Code to call a function/action...
            //return new Rotativa.ActionAsPdf("PrintRptInPDF", reporttransactiondata) 

            //oRotativaPDF = new Rotativa.ViewAsPdf(viewFileToPrint, reporttransactiondata)
            //        {
            //            FileName = "Technician Job Report.pdf",
            //            PageSize = Size.A4,
            //            PageOrientation = Orientation.Portrait,
            //            PageMargins = new Margins(0, 0, 0, 0),
            //            PageWidth = 230,      //250      //300  // 350
            //            PageHeight = 360,      // 380   // 400 //420  // 450
            //            CustomSwitches = "--disable-smart-shrinking"
            //        };

            oRotativaPDF = new Rotativa.PartialViewAsPdf(viewFileToPrint, reporttransactiondata)
            {
                FileName = "Technician Job Report.pdf",
                PageSize = Size.A4,
                PageOrientation = Orientation.Portrait,
                PageMargins = new Margins(0, 0, 0, 0),
                PageWidth = 230,      //250      //300  // 350
                PageHeight = 360,      // 380   // 400 //420  // 450
                CustomSwitches = "--disable-smart-shrinking"
            };
        }
        catch (Exception ex)
        {
            // TODO: Code here...
        }

        return oRotativaPDF;
    }

请忽略注释代码。这工作得很好,但是当我部署 Web 应用程序时,客户端不会下载 PDF 文件,并且一段时间后我的 IE 浏览器会显示 500 内部服务器错误。

我进一步探讨了这个问题,发现这个错误可能是因为 wkhtmltopdf.exe 没有在 Azure 平台上自行执行。因此,我在网上搜索有关问题解决方案的帮助下得出了以下解决方案......

公共(public) ActionResult 生成 PDF(int id = 0) { ReportTransactionData reporttransactiondata = db.ReportTransactionDatas.Find(id); 字符串 viewName = @"~/Views/ReportTranData/PDFReport.cshtml"; 字符串 wkhtmltopdfPath = Server.MapPath(@"~/Rotativa/"); 字符串开关 = string.Empty; 尝试 { if (报告交易数据 == null) { 返回 HttpNotFound(); }

            string fullPath = Server.MapPath(@"~/ApplicationFiles/TechnicianJobReport.pdf");
            FileInfo objFileInfo = new System.IO.FileInfo(fullPath);
            if (objFileInfo.Exists)
            {
                objFileInfo.Delete();
            }

            string sViewString = RenderRazorViewToString(viewName, reporttransactiondata);
            var byteArray = ConvertHTMLtoPDF(wkhtmltopdfPath, switches, sViewString);
            var fileStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
            fileStream.Write(byteArray, 0, byteArray.Length);
            fileStream.Close();

            // Download file at client side...
            Response.Clear();
            Response.ClearContent();
            Response.ClearHeaders();
            Response.Charset = "UTF-8";
            Response.ContentEncoding = Encoding.UTF8;
            Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(objFileInfo.Name));
            Response.ContentType = "application/pdf";
            Response.WriteFile(objFileInfo.FullName);
            Response.End();

        }
        catch (Exception ex)
        {
            // Handle exception here and Log Error to file...
            Repositories.Repository objRepository = new Repositories.Repository();
            string sLogFilePath = Server.MapPath(@"~/ApplicationFiles/ErrorLogFile.txt");
            objRepository.LogErrorToFile(ex, sLogFilePath, this.ControllerContext.Controller.ToString());
        }

        return View(reporttransactiondata);
    }
    public string RenderRazorViewToString(string viewName, object model)
    {
        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }

    /// <summary>
    /// Converts given URL or HTML string to PDF.
    /// </summary>
    /// <param name="wkhtmltopdfPath">Path to wkthmltopdf.</param>
    /// <param name="switches">Switches that will be passed to wkhtmltopdf binary.</param>
    /// <param name="html">String containing HTML code that should be converted to PDF.</param>
    /// <returns>PDF as byte array.</returns>
    private static byte[] ConvertHTMLtoPDF(string wkhtmltopdfPath, string switches, string html)
    {
        // switches:
        //     "-q"  - silent output, only errors - no progress messages
        //     " -"  - switch output to stdout
        //     "- -" - switch input to stdin and output to stdout
        switches = "-q " + switches + " -";

        // generate PDF from given HTML string, not from URL
        if (!string.IsNullOrEmpty(html))
            switches += " -";

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

        // generate PDF from given HTML string, not from URL
        if (!string.IsNullOrEmpty(html))
        {
            using (var sIn = proc.StandardInput)
            {
                sIn.WriteLine(html);
            }
        }

        var ms = new MemoryStream();
        using (var sOut = proc.StandardOutput.BaseStream)
        {
            byte[] buffer = new byte[4096];
            int read;

            while ((read = sOut.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
        }

        string error = proc.StandardError.ReadToEnd();

        if (ms.Length == 0)
        {
            throw new Exception(error);
        }

        proc.WaitForExit();

        return ms.ToArray();
    }

但这在本地主机上再次工作正常,但在 Azure 服务器上却不行,并给出相同的 500 内部服务器错误,没有任何异常。请看看这里是否有人可以提供帮助。我使用这个 wkhtmltopdf exe 因为我可以根据我的(A4 页面大小的一半)纸张尺寸要求指定 pdf 的高度和宽度。如果有任何其他选项可能不会导致我最终遇到执行外部 exe 或 dll 的问题,请也建议该选项。

最佳答案

像 (#Fabrizio Accatino) 写道:Rotativa 正在运行 wkhtmltopdf.exe。它位于项目根目录下的“Rotativa”文件夹中。所以问题可能是:

  1. 在部署期间 - 不会创建 Rotativa 文件夹(确保您已在项目中添加该文件夹和 .exe 并将该文件的属性设置为“始终复制”)。
  2. 服务器上缺少库(确保服务器上存在 - msvcp120.dll 和 msvcr120.dll/在 sysWOW64 文件夹/下)
  3. 确保应用池用户拥有运行可执行文件和存储临时 .pdf 文件所需的权限。
  4. 确保路径名称不超过最大长度(我认为是 250 位数字)。

我希望这能指导您解决问题。

关于pdf - 我正在使用 Rotativa 工具来显示 pdf。它在本地主机上运行良好,但在 Azure 平台上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28940062/

相关文章:

java - 将 excel 文件转换为 pdf 文件

php - 将 PDF 转换为字符串

azure - FluentMigrator 从 Application_Start 迁移

azure - Service Fabric 默认发布配置文件而不是 Local.xml

jquery - 使用 ASP.NET MVC Jquery Ajax 序列化表单对象和集合

c# - 计算 html 分页符 (html 2 pdf) 服务器端,用于使用页眉和页脚进行精确的打印布局

javascript - 如何从浏览器打印 PDF

Azure REST API 获取资源parentResourcePath 参数

asp.net-mvc - asp.net mvc 和类似门户的功能

java - 有推荐的 Jrun Java 1.4 MVC 框架吗?