【问题标题】:MVC Saving ActionResult to byte arrayMVC 将 ActionResult 保存到字节数组
【发布时间】:2012-11-15 11:39:28
【问题描述】:

我正在寻找一种将 MVC ActionResult 保存到字节数组(文件)的好方法。原因是我正在使用 Rotativa 将 HTML 视图转换为 PDF。这很好用,并在浏览器中用 PDF 返回我的用户。现在我想从服务器发送一封电子邮件,包括相同的 PDF 作为附件。为了发送电子邮件,我使用 ActionMailer.Net nuget 包。可以选择将字节数组作为附件。

所以我需要将一个字节数组与我的 PDF 文件一起传递给发送邮件方法。但是返回 PDF 的操作将 ActionResult 作为返回类型,而不是 FileStreamResult(不幸的是)。我不完全知道为什么会做出这个选择,但就是这样。

Rotativa 包使用 Wkhtmltopdf 来转换 HTML。我想我可以自己实现,但这似乎毫无意义,因为我已经有一个方法可以返回我需要的东西;我只需要一种方法将该结果转换为字节数组。

【问题讨论】:

  • 哇,我刚刚遇到了与 Rotativa 完全相同的问题,也想通过电子邮件发送 PDF 并且刚刚找到您的线程...我最终认为我需要将 ActionResult 保存为流好吧..我认为这是最简单的选择,因为其他 PDF 库太复杂/凌乱且矫枉过正。 Rotativa 只是工作..

标签: asp.net-mvc


【解决方案1】:

您可以继承“ViewAsPdf”并创建一个方法来调用“ViewAsPdf”的一些受保护方法:

public class ViewAsPdf2 : ViewAsPdf
{
    public ViewAsPdf2(string viewName, object model) : base(viewName, model) { }
    public byte[] GetByte(ControllerContext context)
    {
        base.PrepareResponse(context.HttpContext.Response);
        base.ExecuteResult(context);
        return base.CallTheDriver(context);
    }
}

在你的行动中:

var pdf = new ViewAsPdf2("MyView", model);
var pdfByteArray = pdf.GetByte(ControllerContext);
SendEmail(pdfByteArray);
return null;

所以您可以使用byte[] 做您想做的事,返回的将是 PDF。

【讨论】:

    【解决方案2】:

    您可以向控制器操作发送 HTTP 请求,该请求应该返回 PDF 并将结果保存为字节数组。 WebClient.DownloadData 方法似乎很合适。

    如果要保留上下文(Session、Authenticated User)则需要设置 Cookie 标头:

    client.Headers[HttpRequestHeader.Cookie] = Request.Headers["Cookie"];
    

    【讨论】:

    • 是否处理上下文?登录用户,诸如此类?
    • 不,它没有。您必须为请求提供必要的 cookie。您可以通过在发送请求之前设置client.Headers[HttpRequestHeader.Cookie] 属性来做到这一点 - Request.Headers["Cookie"]。这样,您将传输上下文。我已经更新了我的答案以提供一个例子。
    【解决方案3】:

    我有同样的问题,这是我的解决方案:

    您基本上需要向自己的 URL 发出 HTTP 请求,并将输出保存为二进制文件。简单 as,没有重载、辅助类和臃肿的东西。

    你需要这个方法:

        // Returns the results of fetching the requested HTML page.
        public static void SaveHttpResponseAsFile(string RequestUrl, string FilePath)
        {
            try
            {
                HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(RequestUrl);
                httpRequest.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";
                httpRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
                HttpWebResponse response = null;
                try
                {
                    response = (HttpWebResponse)httpRequest.GetResponse();
                }
                catch (System.Net.WebException ex)
                {
                    if (ex.Status == WebExceptionStatus.ProtocolError)
                        response = (HttpWebResponse)ex.Response;
                }
    
                using (Stream responseStream = response.GetResponseStream())
                {
                    Stream FinalStream = responseStream;
                    if (response.ContentEncoding.ToLower().Contains("gzip"))
                        FinalStream = new GZipStream(FinalStream, CompressionMode.Decompress);
                    else if (response.ContentEncoding.ToLower().Contains("deflate"))
                        FinalStream = new DeflateStream(FinalStream, CompressionMode.Decompress);
    
                    using (var fileStream = System.IO.File.Create(FilePath))
                    {
                        FinalStream.CopyTo(fileStream);
                    }
    
                    response.Close();
                    FinalStream.Close();
                }
            }
            catch
            { }
        }
    

    然后在你的控制器内部,你可以这样称呼它:

    SaveHttpResponseAsFile("http://localhost:52515/Management/ViewPDFInvoice/" + ID.ToString(), "C:\\temp\\test.pdf");
    

    还有哇!该文件在您的文件系统中,您可以双击并打开 PDF,或通过电子邮件将其发送给您的用户,或者您需要的任何内容...

    【讨论】:

      猜你喜欢
      • 2021-05-25
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 2013-10-27
      • 2018-01-16
      • 2013-10-18
      • 1970-01-01
      • 2011-12-20
      相关资源
      最近更新 更多