C# 如何在MVC中将PDF返回到浏览器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1510451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return PDF to browser in MVC?
提问by Tony Borf
I have this demo code for iTextSharp
我有 iTextSharp 的演示代码
Document document = new Document();
try
{
PdfWriter.GetInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));
document.Open();
document.Add(new Paragraph("Hello World"));
}
catch (DocumentException de)
{
Console.Error.WriteLine(de.Message);
}
catch (IOException ioe)
{
Console.Error.WriteLine(ioe.Message);
}
document.Close();
How do I get the controller to return the pdf document to the browser?
如何让控制器将 pdf 文档返回到浏览器?
EDIT:
编辑:
Running this code does open Acrobat but I get an error message "The file is damaged and could not be repaired"
运行此代码确实打开了 Acrobat,但我收到一条错误消息“文件已损坏,无法修复”
public FileStreamResult pdf()
{
MemoryStream m = new MemoryStream();
Document document = new Document();
PdfWriter.GetInstance(document, m);
document.Open();
document.Add(new Paragraph("Hello World"));
document.Add(new Paragraph(DateTime.Now.ToString()));
m.Position = 0;
return File(m, "application/pdf");
}
Any ideas why this does not work?
任何想法为什么这不起作用?
采纳答案by Tony Borf
I got it working with this code.
我用这段代码让它工作。
using iTextSharp.text;
using iTextSharp.text.pdf;
public FileStreamResult pdf()
{
MemoryStream workStream = new MemoryStream();
Document document = new Document();
PdfWriter.GetInstance(document, workStream).CloseStream = false;
document.Open();
document.Add(new Paragraph("Hello World"));
document.Add(new Paragraph(DateTime.Now.ToString()));
document.Close();
byte[] byteInfo = workStream.ToArray();
workStream.Write(byteInfo, 0, byteInfo.Length);
workStream.Position = 0;
return new FileStreamResult(workStream, "application/pdf");
}
回答by Chris Kooken
You can create a custom class to modify the content type and add the file to the response.
您可以创建自定义类来修改内容类型并将文件添加到响应中。
回答by Geoff
Return a FileContentResult
. The last line in your controller action would be something like:
返回一个FileContentResult
. 控制器操作中的最后一行类似于:
return File("Chap0101.pdf", "application/pdf");
If you are generating this PDF dynamically, it may be better to use a MemoryStream
, and create the document in memory instead of saving to file. The code would be something like:
如果您动态生成此 PDF,最好使用MemoryStream
, 并在内存中创建文档而不是保存到文件。代码类似于:
Document document = new Document();
MemoryStream stream = new MemoryStream();
try
{
PdfWriter pdfWriter = PdfWriter.GetInstance(document, stream);
pdfWriter.CloseStream = false;
document.Open();
document.Add(new Paragraph("Hello World"));
}
catch (DocumentException de)
{
Console.Error.WriteLine(de.Message);
}
catch (IOException ioe)
{
Console.Error.WriteLine(ioe.Message);
}
document.Close();
stream.Flush(); //Always catches me out
stream.Position = 0; //Not sure if this is required
return File(stream, "application/pdf", "DownloadName.pdf");
回答by NerdFury
If you return a FileResult
from your action method, and use the File()
extension method on the controller, doing what you want is pretty easy. There are overrides on the File()
method that will take the binary contents of the file, the path to the file, or a Stream
.
如果你FileResult
从你的 action 方法返回 a ,并File()
在控制器上使用扩展方法,做你想做的事情就很容易了。File()
方法上有一些覆盖,这些方法将采用文件的二进制内容、文件路径或Stream
.
public FileResult DownloadFile()
{
return File("path\to\pdf.pdf", "application/pdf");
}
回答by littlechris
I've run into similar problems and I've stumbled accross a solution. I used two posts, one from stackthat shows the method to return for download and another onethat shows a working solution for ItextSharp and MVC.
我遇到了类似的问题,我偶然发现了一个解决方案。我使用了两篇文章,一篇来自堆栈,显示返回下载的方法,另一篇显示 ItextSharp 和 MVC 的工作解决方案。
public FileStreamResult About()
{
// Set up the document and the MS to write it to and create the PDF writer instance
MemoryStream ms = new MemoryStream();
Document document = new Document(PageSize.A4.Rotate());
PdfWriter writer = PdfWriter.GetInstance(document, ms);
// Open the PDF document
document.Open();
// Set up fonts used in the document
Font font_heading_1 = FontFactory.GetFont(FontFactory.TIMES_ROMAN, 19, Font.BOLD);
Font font_body = FontFactory.GetFont(FontFactory.TIMES_ROMAN, 9);
// Create the heading paragraph with the headig font
Paragraph paragraph;
paragraph = new Paragraph("Hello world!", font_heading_1);
// Add a horizontal line below the headig text and add it to the paragraph
iTextSharp.text.pdf.draw.VerticalPositionMark seperator = new iTextSharp.text.pdf.draw.LineSeparator();
seperator.Offset = -6f;
paragraph.Add(seperator);
// Add paragraph to document
document.Add(paragraph);
// Close the PDF document
document.Close();
// Hat tip to David for his code on stackoverflow for this bit
// https://stackoverflow.com/questions/779430/asp-net-mvc-how-to-get-view-to-generate-pdf
byte[] file = ms.ToArray();
MemoryStream output = new MemoryStream();
output.Write(file, 0, file.Length);
output.Position = 0;
HttpContext.Response.AddHeader("content-disposition","attachment; filename=form.pdf");
// Return the output stream
return File(output, "application/pdf"); //new FileStreamResult(output, "application/pdf");
}
回答by JML
You would normally do a Response.Flush followed by a Response.Close, but for some reason the iTextSharp library doesn't seem to like this. The data doesn't make it through and Adobe thinks the PDF is corrupt. Leave out the Response.Close function and see if your results are better:
您通常会先执行 Response.Flush,然后执行 Response.Close,但出于某种原因,iTextSharp 库似乎不喜欢这样。数据无法通过,Adobe 认为 PDF 已损坏。省略 Response.Close 函数,看看你的结果是否更好:
Response.Clear();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-disposition", "attachment; filename=file.pdf"); // open in a new window
Response.OutputStream.Write(outStream.GetBuffer(), 0, outStream.GetBuffer().Length);
Response.Flush();
// For some reason, if we close the Response stream, the PDF doesn't make it through
//Response.Close();
回答by hutchonoid
I know this question is old but I thought I would share this as I could not find anything similar.
我知道这个问题很老,但我想我会分享这个,因为我找不到任何类似的东西。
I wanted to create my views/models as normal using Razorand have them rendered as Pdfs.
我想使用 Razor像往常一样创建我的视图/模型,并将它们呈现为 Pdfs。
This way I had control over the pdf presentation using standard html output rather than figuring out how to layout the document using iTextSharp.
这样我就可以使用标准的 html 输出来控制 pdf 演示文稿,而不是弄清楚如何使用 iTextSharp 来布局文档。
The project and source code is available here with nuget installation instructions:
项目和源代码可在此处获得,并附有 nuget 安装说明:
https://github.com/andyhutch77/MvcRazorToPdf
https://github.com/andyhutch77/MvcRazorToPdf
Install-Package MvcRazorToPdf
回答by Machinegon
You must specify :
您必须指定:
Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
return new FileStreamResult(stream, "application/pdf")
For the file to be opened directlyin the browser instead of being downloaded
直接在浏览器中打开文件而不是下载文件
回答by ethiraj
if you return var-binary data from DB to display PDF on popup or browser means follow this code:-
如果您从 DB 返回 var-binary 数据以在弹出窗口或浏览器上显示 PDF 意味着请遵循以下代码:-
View page:
查看页面:
@using (Html.BeginForm("DisplayPDF", "Scan", FormMethod.Post))
{
<a href="javascript:;" onclick="document.forms[0].submit();">View PDF</a>
}
Scan controller:
扫描控制器:
public ActionResult DisplayPDF()
{
byte[] byteArray = GetPdfFromDB(4);
MemoryStream pdfStream = new MemoryStream();
pdfStream.Write(byteArray, 0, byteArray.Length);
pdfStream.Position = 0;
return new FileStreamResult(pdfStream, "application/pdf");
}
private byte[] GetPdfFromDB(int id)
{
#region
byte[] bytes = { };
string constr = System.Configuration.ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "SELECT Scan_Pdf_File FROM PWF_InvoiceMain WHERE InvoiceID=@Id and Enabled = 1";
cmd.Parameters.AddWithValue("@Id", id);
cmd.Connection = con;
con.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
if (sdr.HasRows == true)
{
sdr.Read();
bytes = (byte[])sdr["Scan_Pdf_File"];
}
}
con.Close();
}
}
return bytes;
#endregion
}
回答by S.J.Lee
HttpContext.Response.AddHeader("content-disposition","attachment; filename=form.pdf");
if the filename is generating dynamically then how to define filename here, it is generating through guid here.
如果文件名是动态生成的,那么这里如何定义文件名,这里是通过guid生成的。