我正在使用 Rotativa 工具来显示 pdf.它在本地主机上运行良好,但在 Azure 平台上不起作用 [英] I am using Rotativa tool to display pdf. It works fine on localhost, But does not work on Azure platform

查看:17
本文介绍了我正在使用 Rotativa 工具来显示 pdf.它在本地主机上运行良好,但在 Azure 平台上不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Rotativa 工具 来显示 PDF.它在 localhost 上运行良好,但在 Azure 平台上不起作用.

I am using Rotativa tool to display PDF. It works fine on localhost, But does not work on Azure platform.

下面是我的代码...

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;
    }

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

Please ignore the commented code. This works just fine but when I deploy my web application, the PDF file is not downloaded at client side and after some time my IE browser display 500 internal server error.

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

I explored the issue further and came to know that this error may be because wkhtmltopdf.exe does not execute on its own on Azure platform. So I came with the following solution with the help of some search on the net about the issue resolution...

public ActionResult GeneratePDF(int id = 0){ReportTransactionData reporttransactiondata = db.ReportTransactionDatas.Find(id);string viewName = @"~/Views/ReportTranData/PDFReport.cshtml";string wkhtmltopdfPath = Server.MapPath(@"~/Rotativa/");字符串开关 = string.Empty;尝试{if (reporttransactiondata == null){返回 HttpNotFound();}

public ActionResult GeneratePDF(int id = 0) { ReportTransactionData reporttransactiondata = db.ReportTransactionDatas.Find(id); string viewName = @"~/Views/ReportTranData/PDFReport.cshtml"; string wkhtmltopdfPath = Server.MapPath(@"~/Rotativa/"); string switches = string.Empty; try { if (reporttransactiondata == null) { return 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();
    }

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

But this again works fine on localhost but not on Azure server and gives the same 500 internal server error with no exception at all. Please see if anyone can help here. I am using this wkhtmltopdf exe because I can specify the height and width of the pdf according to my (half of A4 page size) paper size requirement. If there is any other option where I may not end up in the issue of executing an external exe or dll, please suggest that option too.

推荐答案

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

Like (#Fabrizio Accatino) wrote: Rotativa is running wkhtmltopdf.exe. It is located in "Rotativa" folder under the root of your project. So the issue could be:

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

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

I hope this will guide you for solving the problem.

这篇关于我正在使用 Rotativa 工具来显示 pdf.它在本地主机上运行良好,但在 Azure 平台上不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆