将MVC的ActionResult保存为字节数组

3
我正在寻找一种很好的方法将MVC ActionResult保存为byte数组(文件)。这是因为我正在使用Rotativa将HTML视图转换为PDF。它可以很好地工作并在浏览器中返回给用户PDF文件。现在,我想从服务器发送电子邮件,并作为附件包含相同的PDF文件。对于发送电子邮件,我正在使用ActionMailer.Net nuget包。它有将byte数组作为附件的选项。
因此,我需要将我的PDF文件作为一个byte数组传递给发送邮件的方法。但是返回PDF的操作的返回类型是ActionResult而不是FileStreamResult(不幸的是)。我不太清楚为什么会做出这个选择,但就是这样。
Rotativa软件包使用Wkhtmltopdf来进行HTML转换。我猜我可以自己实现这个过程,但那似乎有点无意义,因为我已经有了一个返回我所需结果的方法;我只需要一种将结果转换为byte数组的方法。

哇,我正在处理与Rotativa相关的完全相同的问题,并想要通过电子邮件发送PDF文件,刚刚找到了你的线程... 我最终认为我还需要将ActionResult保存为流..我认为这是最简单的选择,因为其他PDF库过于复杂/混乱和过度臃肿。Rotativa只需要工作即可。 - Aaron
3个回答

6
你可以继承 '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 文件。

0

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

如果您想保留上下文(会话、已验证的用户),则需要设置Cookie标头:

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

那个处理上下文吗?已登录的用户,这样的东西? - Jasper
不,它不会。您必须为请求提供必要的cookie。您可以在发送请求之前设置client.Headers[HttpRequestHeader.Cookie]属性 - Request.Headers["Cookie"]。这样,您将传输上下文。我已更新我的答案以提供示例。 - Darin Dimitrov

0

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

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

你需要这个方法:

    // 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文件,或将其发送电子邮件给用户,或进行其他操作...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接