-->

如何拦截.NET MVC3当前的ActionResult的输出流?(How do I interce

2019-06-26 20:50发布

Hi和感谢寻找!

背景

我现在用的是Rotativa PDF工具读取视图(HTML)转换成PDF。 它的伟大工程,但它本身不提供一种方法来PDF保存到文件系统。 相反,它只返回文件到用户的浏览器作为操作的结果。

下面是该代码的样子:

public ActionResult PrintQuote(FormCollection fc)
        {
            int revisionId = Int32.Parse(Request.QueryString["RevisionId"]);

            var pdf = new ActionAsPdf(
                 "Quote",
                 new { revisionId = revisionId })
                       {
                           FileName = "Quote--" + revisionId.ToString() + ".pdf",
                           PageSize = Rotativa.Options.Size.Letter
                       };

            return pdf;

        } 

此代码调用其他的ActionResult(“报价”),它的观点转换为PDF,然后返回PDF的文件下载到用户。

如何截取文件流并保存PDF到我的文件系统。 它是完美的PDF发送给用户,但我的客户也希望同时保存到文件系统中的PDF。

有任何想法吗?

谢谢!

马特

Answer 1:

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

你需要做基本的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,或通过电子邮件发送给您的用户,或任何你需要的。



Answer 2:

 return new Rotativa.ActionAsPdf("ConvertIntoPdf") 
 { 
     FileName = "Test.pdf", PageSize = Rotativa.Options.Size.Letter
 };


Answer 3:

看看MVC的管道图在这里: http://www.simple-talk.com/content/file.ashx?file=6068

该方法OnResultExecuted()的ActionResult的呈现之后被调用。

您可以覆盖此方法,或者使用ActionFilter申请和使用属性OnResultExecuted拦截。

编辑:在结束这个论坛主题 ,你会发现一个答复赋予一个ActionFilter它能读取(变化)行动的响应流中的一个例子。 然后,您可以将流复制到文件中,除了将其返回到客户端。



Answer 4:

我成功地利用亚伦的“SaveHttpResponseAsFile”的方法,但我不得不改变它,在用户的凭据当前登录不适用(因此它被转发到MVC4的登录网址)。

public static void SaveHttpResponseAsFile(System.Web.HttpRequestBase requestBase, string requestUrl, string saveFilePath)
{
    try
    {
        *snip*
        httpRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
        httpRequest.Headers.Add(HttpRequestHeader.Cookie, requestBase.Headers["Cookie"]);
        *snip*</pre></code>

然后在您的呼叫控制器方法,只需添加“请”到SaveHttpResponseAsFile通话。



Answer 5:

您也可以使用Rotativa,这实际上是很容易做到这一点。

Using Rotativa;

...

byte[] pdfByteArray = Rotativa.WkhtmltopdfDriver.ConvertHtml( "Rotativa", "-q", stringHtmlResult );

File.WriteAllBytes( outputPath, pdfByteArray );

我在WinForms应用程序使用此,生成和保存从剃刀查看PDF文件,我们还使用我们的Web应用程序。



Answer 6:

我能得到埃里克·布朗-卡尔的解决方案的工作,但我需要一个小的调整,以防止出现错误我得到关于未找到目录

(另外,在看Rotativa代码,它看起来像-q开关已经被默认情况下通过,因此这可能不是必要的,但我并没有改变它。)

var bytes = Rotativa.WkhtmltopdfDriver.ConvertHtml(Server.MapPath(@"/Rotativa"), "-q", html);


文章来源: How do I intercept the output stream of the current actionresult in .NET MVC3?