如何在 .NET MVC3 中截获当前操作结果的输出流
本文关键字:操作 结果 输出流 NET MVC3 | 更新日期: 2024-11-08 16:07:55
您好,感谢您的查看!
背景
我正在使用 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;
}
此代码调用另一个操作结果("引用"),将其视图转换为 PDF,然后将 PDF 作为文件下载返回给用户。
问题
如何截获文件流并将 PDF 保存到我的文件系统。 将PDF发送给用户是完美的,但是我的客户还希望将PDF同时保存到文件系统中。
有什么想法吗?
谢谢!
马 特
我有同样的问题,这是我的解决方案:
您基本上需要对自己的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,或通过电子邮件将其发送给您的用户,或任何您需要的内容。
return new Rotativa.ActionAsPdf("ConvertIntoPdf")
{
FileName = "Test.pdf", PageSize = Rotativa.Options.Size.Letter
};
看看这里的 MVC 流水线图:http://www.simple-talk.com/content/file.ashx?file=6068
方法 OnResultExecuted() 在呈现 ActionResult 后调用。
您可以重写此方法,也可以使用属性使用 ActionFilter 应用和 OnResultExecute 拦截器。
编辑:在此论坛主题的末尾,您将找到一个回复,其中给出了一个 ActionFilter 的示例,该过滤器读取(并更改)操作的响应流。然后,除了将其返回到客户端之外,还可以将流复制到文件。
我成功地使用了Aaron的"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 调用中。
您也可以使用Rotativa来做到这一点,这实际上非常简单。
Using Rotativa;
...
byte[] pdfByteArray = Rotativa.WkhtmltopdfDriver.ConvertHtml( "Rotativa", "-q", stringHtmlResult );
File.WriteAllBytes( outputPath, pdfByteArray );
我正在Winforms应用程序中使用它,以从我们也在Web应用程序中使用的Razor视图生成和保存PDF。
我能够让 Eric Brown - Cal 的解决方案工作,但我需要进行一个小的调整以防止我得到的关于找不到目录的错误。
(另外,查看 Rotativa 代码,看起来默认情况下已经传递了 -q 开关,所以这可能不是必需的,但我没有更改它。
var bytes = Rotativa.WkhtmltopdfDriver.ConvertHtml(Server.MapPath(@"/Rotativa"), "-q", html);