How to open PDF Document programatically without saving it? - c#

I have PDF document saved into my PDFs folder. I have created one function whose duty is to load the PDF into PdfDocument class, add some styles on runtime, save it back as temporary file and preview it in WebClient. My logic is working absolutely fine. I want to eliminate saving it back as temporary file. I want to directly preview it without saving, is it possible? I searched online but didn't get any good source. Following is my code:
PdfDocument pdf = new PdfDocument();
pdf.LoadFromFile("MyFile.pdf");
pdf.SaveToFile("ModifiedMyFile.pdf"); // Eliminate this part
WebClient User = new WebClient();
Byte[] FileBuffer = User.DownloadData("ModifiedMyFile.pdf");
if (FileBuffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", FileBuffer.Length.ToString());
Response.BinaryWrite(FileBuffer);
}

According to spire's documentation, you have two ways to do that
Using SaveToHttpResponse() method
https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/How-to-Create-PDF-Dynamically-and-Send-it-to-Client-Browser-Using-ASP.NET.html
PdfDocument pdf = new PdfDocument();
pdf.LoadFromFile("MyFile.pdf");
.... edit the document
pdf.SaveToHttpResponse("sample.pdf",this.Response, HttpReadType.Save);
Or, if the built-in method doesn't work, try to use a memory stream instead of a temporary file.
https://www.e-iceblue.com/Tutorials/Spire.PDF/Spire.PDF-Program-Guide/Document-Operation/Save-PDF-file-to-Stream-and-Load-PDF-file-from-Stream-in-C-.NET.html
PdfDocument pdf = new PdfDocument();
.... edit the document
using (MemoryStream ms = new MemoryStream())
{
pdfDocument.SaveToStream(ms);
Byte[] bytes = ms.ToArray();
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", bytes.Length.ToString());
Response.BinaryWrite(bytes);
}

Related

Creating PDF from C# using iTextSharp produces 0 byte file

I've searched through most of the 300+ posts on this topic and cannot find one that addresses this issue specifically.
I tried the simplest of file creators with the same result: (from http://www.codeproject.com/Articles/686994/Create-Read-Advance-PDF-Report-using-iTextSharp-in#1) I found this link in another post.
public byte[] generatePublicationCitationReport(List<int> pubIDs)
{
//Step 1: Create a System.IO.FileStream object:
MemoryStream ms = new MemoryStream();
//Step 2: Create a iTextSharp.text.Document object:
Document doc = new Document();
//Step 3: Create a iTextSharp.text.pdf.PdfWriter object. It helps to write the Document to the Specified FileStream:
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
//Step 4: Openning the Document:
doc.Open();
//Step 5: Adding a Paragraph by creating a iTextSharp.text.Paragraph object:
doc.Add(new Paragraph("Hello World"));
//Step 6: Closing the Document:
doc.Close();
return ms.ToArray();
}
The code was modified slightly changing the "filestream" to "memorystream" and passing that back to the calling function to open the file.
The code above generates a 0 byte file and tries to open it. When opening fails, I get an error message indicating "Failed to load PDF file."
I'm trying to generate a PDF file from a list of citations created from data in an SQL database. I'm getting the data properly and can display it using Response.Write.
In my code I add a loop to create each citation individually and add it to the paragraph.
iTextSharp.text.Paragraph paragraph1 = new iTextSharp.text.Paragraph();
iTextSharp.text.Paragraph paraCitations = new iTextSharp.text.Paragraph();
iTextSharp.text.Paragraph paragraph3 = new iTextSharp.text.Paragraph();
iTextSharp.text.Chunk chunk1 = new iTextSharp.text.Chunk("Chunky stuff here...");
paragraph1.Add("Paragraph stuff goes here...");
for (int i = 0; i < pubIDs.Count; i++)
{
string pubCitation = createPubCitation(pubIDs[i]);
chunk1.Append(pubCitation);
paraCitations.Add(chunk1);
}
paragraph3.Add("New paragraph - paraCitations - goes here");
doc.Add(paragraph1);
doc.Add(paraCitations);
doc.Add(paragraph3);
doc.Close();
return ms.toArray();
}
Any suggestions? Pointers? Answer?
Thanks,
Bob
This is the call to and return from the procedure to create the PDF file and open it...
pubCitationAsPDF = p.generatePublicationCitationReport(pubIDs);
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=publicationCitations.pdf");
Response.End();
Response.Flush();
Response.Clear();
As per comments, it appears your issue is more related to how you download the file, vs creating the file.
Your code for downloading does not include adding the bytes from your memory stream to your response.
Change your download code to this:
Response.Clear();
Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", "attachment; filename=publicationCitations.pdf");
// This is the piece you're missing
Response.BinaryWrite(p.generatePublicationCitationReport(pubIDs));
Response.End();

How to open a pdf file in the web browser?

I want to display a pdf. My current code displayit using a pdf reader. But I want to open it in a seperate tab of the browser. How can i do it? I have a link button inside the web page. I have set this in onClick method. How to open it using back end code? (not using a link in aspx)
Here is my code
string name = ddlAppealList.SelectedValue.ToString();
int refNo = Convert.ToInt32(name);
string FilePath = Server.MapPath("~/filesPDF/" + refNo + ".pdf");
WebClient User = new WebClient();
Byte[] FileBuffer = User.DownloadData(FilePath);
if (FileBuffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", FileBuffer.Length.ToString());
Response.BinaryWrite(FileBuffer);
}
Response.ContentType = "Application/pdf";
Response.TransmitFile(PDFfilepath);
For opening the PDF file in a new tab or windows you can use following html code:
View
I hope it helps you.
I encountered a similar situation a few weeks ago. This piece of code, inspired by this answer, helped me solve the issue:
Response.AppendHeader("Content-Disposition", new System.Net.Mime.ContentDisposition { Inline = true, FileName = "pdfname.pdf" }.ToString());
Here is an example to open a pdf in a C# web application with ActionResult. You can also store the pdf as a byte[] in the database to make this code simpler.
public async Task<ActionResult> ViewPdf()
{
MemoryStream ms = new MemoryStream();
FileStream stream = new FileStream("mypdf.pdf", FileMode.Open, FileAccess.Read);
stream.CopyTo(ms);
return File(ms.ToArray(), "application/pdf");
}

Generate a pdf without saving it to disk then show it to browser

Is it possible to merged pdf file without saving it to disk?
I have a generated pdf (via itextsharp) and a physical pdf file. These two should show to the browser as merged.
What I currently have is, (a pseudo code)
public ActionResult Index()
{
// Generate dyanamic pdf first
var pdf = GeneratePdf();
// Then save it to disk for retrieval later
SaveToDisc(pdf);
// Retrieve the static pdf
var staticPdf = GetStaticPdf();
// Retrieve the generated pdf that was made earlier
var generatedPdf = GetGeneratedPdf("someGeneratedFile.pdf");
// This creates the merged pdf
MergePdf(new List<string> { generatedPdf, staticPdf }, "mergedPdf.pdf");
// Now retrieve the merged pdf and show it to the browser
var mergedPdf = GetMergedPdf("mergedPdf.pdf");
return new FileStreamResult(mergedFile, "application/pdf");
}
This works, but I was just wondering if, would it be possible to just merged the pdf and show it to the browser without saving anything on the disc?
Any help would be much appreciated. Thanks
You can try to use PdfWriter class and MemoryStream like this:
using (MemoryStream ms = new MemoryStream())
{
Document doc = new Document(PageSize.A4, 60, 60, 10, 10);
PdfWriter pw = PdfWriter.GetInstance(doc, ms);
//your code to write something to the pdf
return ms.ToArray();
}
You can also refer: Creating a PDF from a RDLC Report in the Background
Additionally: if data is the PDF in memory, than you need to do data.CopyTo(base.Response.OutputStream);
try this
string path = Server.MapPath("Yourpdf.pdf");
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(path);
if (buffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", buffer.Length.ToString());
Response.BinaryWrite(buffer);
}

Opening a document in PDF as opposed to Word with code on a button click

I have copied code previously used throughout the system i am working on. However this code opens the content in a word document. I am looking it to be opened in a PDF.
I have already tried changing the string declaration 'filename' to end in (.pdf) as opposed to (.doc) but when attempting to open it it says "could not open the document because it is either not a spported file type or because the file has been damaged....".
What changes need to be made to this code in order to open it as an adope pdf. I wouldnt imagine it would be alot.
string content = sw.GetStringBuilder().ToString();
string fileName = "IRPBestPracticeArticle.doc";
Response.AppendHeader("Content-Type", "application/msword; charset=utf-8");
Response.AppendHeader("Content-disposition", "attachment; filename=" + fileName);
Response.Charset = "utf-8";
Response.Write(content);
I cannot say for certain, but I am going to assume you're trying to save your data as a pdf and have it open in whatever application the system uses to read pdf files?
//Note the change from application/msword to application/pdf
Response.AppendHeader("Content-Type", "application/pdf; charset=utf-8");
Make sure to change the mime type as well as the doc ending (See here for full list of mime types):
That being said, I cant guarantee it will open properly in your PDF reader
Just try this set of code.
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "inline;filename=" + fileName);
Response.ContentType = "application/pdf";
Response.WriteFile("FullFilePath");
Response.Flush();
Response.Clear();
Response.End();
The mime type need to be set correctly before opening the file.
Andy try this one. You must have ItextSharp.dll to use this code. Download it from here. Then add its reference in your page.
try this code to create pdf from string and download it
Document document = new Document(PageSize.A4);
using (MemoryStream ms = new MemoryStream())
{
PdfWriter.GetInstance(document, ms);
document.Open();
System.Xml.XmlTextReader _xmlr;
if (String.IsNullOrEmpty(errorMsg))
_xmlr = new System.Xml.XmlTextReader(new StringReader(GetTransferedData(content)));
else
_xmlr = new System.Xml.XmlTextReader(new StringReader(#"<html><body>Error Message:" + errorMsg + "</body></html>"));
iTextSharp.text.html.HtmlParser.Parse(document, _xmlr);
document.Close();
ms.Flush();
byte[] data = ms.ToArray();
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.Buffer = true;
Response.ContentType = "application/pdf";
Response.BinaryWrite(data);
Response.End();
ms.Close();
}
First, convert the .doc files to PDF files. Here is a sample of how to achieve this: Convert Doc file to PDF in VB.Net
After you have the PDF files, stream them to the browser using the "application/pdf" content type.

save the document created by docX into response and send it to user for downloading

I am trying to use the amazing DocX library on codeplex to create a word document.
when the user clicks a button, the document is created and I want to be able to send it to the user immediately via response.. I am doing something similar to this now:
Edited code based on suggestions
using (DocX Report = DocX.Create(string.Format("Report-{0}.doc", DateTime.Now.Ticks)))
{
Paragraph p = Report.InsertParagraph();
p.Append("Title").FontSize(30).Bold()
.Append("Sub title").FontSize(28)
.AppendLine()
.Append(DateTime.Now.Date)
;
MemoryStream ms = new MemoryStream();
Report.SaveAs(ms);
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".docx\"");
Response.ContentType = "application/msword";
Response.Write(ms);
Response.End();
}
I have tried a few variations of this.. but I am not able to achieve what I want.. Looking at this answer I can possibly save the document on the server and open with io stream.. but I want to avoid that extra step (and then I need to delete the file too)
I don't see the point of creating a file for few milli seconds.. there has to be a way to save the contents and send them to response stream.. right?
How'd I go about it?
thanks..
EDIT: my current code either throws up cannot open file (Access denied) error If I am using file stream, OR downloads an empty document file without any content (sometimes, type of response is written to document)
This code gets me an MS word document with System.IO.MemoryStream as it's content..
Okay, here is the final working solution:
For some reason, DocX library doesn't want to save to Response.OutputStream directly, so I had to save it to memory stream and write the memory stream to response, like Neil & Daniel suggested. Here's what worked for me:
MemoryStream ms = new MemoryStream()
Report.SaveAs(ms);
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".doc\");
Response.ContentType = "application/msword";
ms.WriteTo(Response.OutputStream);
Response.End();
This might be a bit late, but I found a way to get this working with FileStreamResult:
public FileStreamResult DownloadDocument()
{
using (DocX document = DocX.Create(#"Test.docx"))
{
// Insert a new Paragraphs.
Paragraph p = document.InsertParagraph();
p.Append("I am ").Append("bold").Bold()
.Append(" and I am ")
.Append("italic").Italic().Append(".")
.AppendLine("I am ")
.Append("Arial Black")
.Font(new FontFamily("Arial Black"))
.Append(" and I am not.")
.AppendLine("I am ")
.Append("BLUE").Color(Color.Blue)
.Append(" and I am")
.Append("Red").Color(Color.Red).Append(".");
var ms = new MemoryStream();
document.SaveAs(ms);
ms.Position = 0;
var file = new FileStreamResult(ms, "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
{
FileDownloadName = string.Format("test_{0}.docx", DateTime.Now.ToString("ddMMyyyyHHmmss"))
};
return file;
}
}
The important bit is setting the Position of the memorystream back to 0, otherwise it appeared to be at the end, and the file was returning empty.
Try using a MemoryStream instead of a FileStream.
Your current code looks really wrong:
You are saving the report to the OutputStream of the current response and then clear that response (!)
When you do Report.SaveAs(response.OutputStream); - it already writes file contents to the output stream. You don't need to do Response.Write(response.OutputStream);
So you code should look like this:
...
Report.SaveAs(response.OutputStream);
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".doc\"");
Response.ContentType = "application/msword";
I think you've got things a little back to front and confused.
First off, clear the output, then add the headers, then write out the content.
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=\"" + fileName + ".doc\"");
Response.ContentType = "application/msword";
// This writes the document to the output stream.
Report.SaveAs(response.OutputStream);
Response.End();
Also , if your file is a docx format file, append .docx rather than .doc to your filename.

Categories

Resources