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

时间:2015-03-09 10:44:55

标签: pdf azure model-view-controller rotativa

我正在使用Rotativa tool来显示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 GeneratePDF(int id = 0)         {             ReportTransactionData reporttransactiondata = db.ReportTransactionDatas.Find(id);             string viewName = @"〜/ Views / ReportTranData / PDFReport.cshtml&#34 ;;             string wkhtmltopdfPath = Server.MapPath(@"〜/ Rotativa /");             string switches = string.Empty;             尝试             {                 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的问题上结束,请同时建议该选项。

3 个答案:

答案 0 :(得分:7)

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

  1. 在部署期间 - 未创建Rotativa文件夹(确保您已在项目中添加了文件夹和.exe,并将文件的属性设置为“始终复制”)。
  2. 服务器上缺少库(确保服务器上显示 - msvcp120.dll和msvcr120.dll / sysWOW64文件夹下/)
  3. 确保应用程序池用户具有运行可执行文件所需的权限并存储临时.pdf文件。
  4. 确保路径名称不超过最大长度(我认为250位)。
  5. 我希望这能指导您解决问题。

答案 1 :(得分:0)

我遇到了同样的问题,我设法通过升级到1.6.3版本的旋转解决了。跟随链接nuget:[https://www.nuget.org/packages/Rotativa/1.6.3] [1]


在程序包管理器控制台中,键入:

  1. 旋转卸载软件包,按Enter。
  2. 安装包旋转版本1.6.3按ENTER。
  3. 签入旋转文件夹,如果您现在只是文件* * wkhtmltopdf。 exe * *。

备注

在1.6.3版本中,旋转不再使用文件:

  1. libeay32。 dll
  2. LIBGCC_S_DW2-1。 dll
  3. MINGWM10。 dll
  4. 自述文件。 txt
  5. ssleay32。 dll

它仅使用以下文件:

  1. wkhtmltopdf。 exe

但是,升级到此新版本时,轮换仅将此文件 wkhtmltopdf.exe 更新为新文件,代替它。

现在只需再次旋转它,它将再次起作用。

[1]:轮换升级到1.6.3版本

答案 2 :(得分:0)

我认为只有天蓝色的高级帐户允许在服务器上运行wkhtmltopdf.exe,或者您也可以使用此https://rotativahq.com/

创建旋转的pdf。

希望对所有人有帮助!