how to save pdf file in client machine in mvc3? - c#

I generate a pdf file on the fly and save it to the server side but i need to save it to the client machine. How to achieve this..
Document doc = new Document();
MemoryStream memoryStream = new MemoryStream();
string PDFName = ProjectName + ".pdf";
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(Server.MapPath("~/ProjectFiles") + "/" +
PDFName, FileMode.Create));
doc.Open();
//PDF Content
doc.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=" + PDFName);
Response.Buffer = true;
Response.Clear();
Response.OutputStream.Write(memoryStream.GetBuffer(), 0, memoryStream.GetBuffer().Length);
Response.OutputStream.Flush();
Response.End();
In Response.OutputStream.Write(memoryStream.GetBuffer(), 0, memoryStream.GetBuffer().Length);
The memoryStream length is 0. I need to download the saved pdf into Cleint machine.
Please help me to fix this issue..

You are not writing anything to memoryStream.
Since you are generating PDFs on each request there is no need to save them to the file. You could generate the PDF to the MemoryStream directly.
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);
If your PDFs are not dynamic (eg. there is no need to generate them on every request) You can generate them to the file system as you do right now and then only read them from disk:
using (MemoryStream ms = new MemoryStream())
{
using (FileStream file = new FileStream(YourPdfFile, FileMode.Open, FileAccess.Read)) {
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
}
}
But this makes sens only if the PDFs are generated once and then only served from disk.
EDIT: after writing into stream it was necessary to set memoryStream position to zero because it was at the end.

You have to affect memorystream like that :
PdfWriter pdfWriter = PdfWriter.GetInstance(document, memoryStream);

Related

How to return PDF using iText

I am trying to return a PDF with simple text, but getting the following error when downloading the document: Failed to load PDF document. Any ideas on how to resolve this is appreciated.
MemoryStream ms = new MemoryStream();
PdfWriter writer = new PdfWriter(ms);
PdfDocument pdfDocument = new PdfDocument(writer);
Document document = new Document(pdfDocument);
document.Add(new Paragraph("Hello World"));
//document.Close();
//writer.Close();
ms.Position = 0;
string pdfName = $"IP-Report-{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.pdf";
return File(ms, "application/pdf", pdfName);
You have to close the writer without closing the underlying stream, which will flush its internal buffer. As is, the document isn't being written to the memory stream in its entirety. Everything but ms should be in a using, too.
You can verify this is occuring by checking the length of ms in your code vs. the code below.
When the using (PdfWriter writer =...) closes, it will close the writer, which causes it to flush its pending writes to the underlying stream ms.
MemoryStream ms = new MemoryStream();
using (PdfWriter writer = new PdfWriter(ms))
using (PdfDocument pdfDocument = new PdfDocument(writer))
using (Document document = new Document(pdfDocument))
{
/*
* Depending on iTextSharp version, you might instead use:
* writer.SetCloseStream(false);
*/
writer.CloseStream = false;
document.Add(new Paragraph("Hello World"));
}
ms.Position = 0;
string pdfName = $"IP-Report-{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.pdf";
return File(ms, "application/pdf", pdfName);

MemoryStream PDF file in ASP.NET Core 2

Keep getting an error 'Cannot access a closed Stream.'
Does the file need to be physically saved on a server first, prior to being Streamed? I am doing the same with Excel file and it works just fine. Trying to use the same principle here with PDF file.
[HttpGet("ExportPdf/{StockId}")]
public IActionResult ExportPdf(int StockId)
{
string fileName = "test.pdf";
MemoryStream memoryStream = new MemoryStream();
// Create PDF document
Document document = new Document(PageSize.A4, 25, 25, 25, 25);
PdfWriter pdfWriter = PdfWriter.GetInstance(document, memoryStream);
document.Open();
document.Add(new Paragraph("Hello World"));
document.Close();
memoryStream.Position = 0;
return File(memoryStream, "application/pdf", fileName);
}
Are you using iText7? If yes, please add that tag onto your question.
using (var output = new MemoryStream())
{
using (var pdfWriter = new PdfWriter(output))
{
// You need to set this to false to prevent the stream
// from being closed.
pdfWriter.SetCloseStream(false);
using (var pdfDocument = new PdfDocument(pdfWriter))
{
...
}
var renderedBuffer = new byte[output.Position];
output.Position = 0;
output.Read(renderedBuffer, 0, renderedBuffer.Length);
...
}
}
Switched to iText& (7.1.1) version as per David Liang comment
Here is the code that worked for me, a complete method:
[HttpGet]
public IActionResult Pdf()
{
MemoryStream memoryStream = new MemoryStream();
PdfWriter pdfWriter = new PdfWriter(memoryStream);
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
Document document = new Document(pdfDocument);
document.Add(new Paragraph("Welcome"));
document.Close();
byte[] file = memoryStream.ToArray();
MemoryStream ms = new MemoryStream();
ms.Write(file, 0, file.Length);
ms.Position = 0;
return File(fileStream: ms, contentType: "application/pdf", fileDownloadName: "test_file_name" + ".pdf");
}

How do I zip a Word document stored in a MemoryStream using ICSharpCode.SharpZipLib.Zip?

I am trying to zip a Word document that is stored in a MemoryStream like this:
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
ZipEntry newEntry = new ZipEntry("my_document.docx");
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
//docMS is a MemoryStream that contains a Word document
StreamUtils.Copy(docMS, zipStream, new byte[4096]);
docMS.Close();
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
context.Response.AddHeader("content-disposition", String.Format("attachment;filename={0}", "my_document.zip"));
context.Response.ContentType = "application/octet-stream";
zipStream.WriteTo(context.Response.OutputStream);
context.Response.End();
When the zip file is downloaded and unzipped, 'my_document.docx' opens up as a blank document. If I modify the code above so that the 'my_document.docx' file is downloaded directly (not zipped) via the MemoryStream 'docMS', then the document opens up fine. I cannot figure out why.

How to email a PDF without opening it

I have this code that creates a PDF file and then emails it. However, when I run it, it opens and will change my entire page to PDF. How can I stop the page to open the PDF?
PdfWriter.GetInstance(document, Response.OutputStream);
Response.ContentType = "application/pdf";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
HTMLWorker htmlparser = new HTMLWorker(document);
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
document.Add(mainTable);
Response.Write(document);
writer.CloseStream = false;
document.Close();
memoryStream.Position = 0;
EmailPresenter.SkyMail asd = new EmailPresenter.SkyMail();
asd.SendMail("test#test.com", "This is a test email...", memoryStream, "Test.pdf");
Response.End();
I do not know this PdfWriter library. But my suggestion would be to not provide the Response.OutputStream to the PdfWriter.
Simply delete the first three lines and the Response stream will remain untouched. You might also want to remove the last line with the Response.End() method call.

Create PDF in memory instead of physical file

How do one create PDF in memorystream instead of physical file using itextsharp.
The code below is creating actual pdf file.
Instead how can I create a byte[] and store it in the byte[] so that I can return it through a function
using iTextSharp.text;
using iTextSharp.text.pdf;
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream("c:\\Test11.pdf", FileMode.Create));
doc.Open();//Open Document to write
Paragraph paragraph = new Paragraph("This is my first line using Paragraph.");
Phrase pharse = new Phrase("This is my second line using Pharse.");
Chunk chunk = new Chunk(" This is my third line using Chunk.");
doc.Add(paragraph);
doc.Add(pharse);
doc.Add(chunk);
doc.Close(); //Close document
Switch the filestream with a memorystream.
MemoryStream memStream = new MemoryStream();
PdfWriter wri = PdfWriter.GetInstance(doc, memStream);
...
return memStream.ToArray();
using iTextSharp.text;
using iTextSharp.text.pdf;
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
byte[] pdfBytes;
using(var mem = new MemoryStream())
{
using(PdfWriter wri = PdfWriter.GetInstance(doc, mem))
{
doc.Open();//Open Document to write
Paragraph paragraph = new Paragraph("This is my first line using Paragraph.");
Phrase pharse = new Phrase("This is my second line using Pharse.");
Chunk chunk = new Chunk(" This is my third line using Chunk.");
doc.Add(paragraph);
doc.Add(pharse);
doc.Add(chunk);
}
pdfBytes = mem.ToArray();
}
I've never used iTextPDF before but it sounded interesting so I took upon the challenge and did some research on my own. Here's how to stream the PDF document via memory.
protected void Page_Load(object sender, EventArgs e)
{
ShowPdf(CreatePDF2());
}
private byte[] CreatePDF2()
{
Document doc = new Document(PageSize.LETTER, 50, 50, 50, 50);
using (MemoryStream output = new MemoryStream())
{
PdfWriter wri = PdfWriter.GetInstance(doc, output);
doc.Open();
Paragraph header = new Paragraph("My Document") {Alignment = Element.ALIGN_CENTER};
Paragraph paragraph = new Paragraph("Testing the iText pdf.");
Phrase phrase = new Phrase("This is a phrase but testing some formatting also. \nNew line here.");
Chunk chunk = new Chunk("This is a chunk.");
doc.Add(header);
doc.Add(paragraph);
doc.Add(phrase);
doc.Add(chunk);
doc.Close();
return output.ToArray();
}
}
private void ShowPdf(byte[] strS)
{
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=" + DateTime.Now);
Response.BinaryWrite(strS);
Response.End();
Response.Flush();
Response.Clear();
}
Where your code has new FileStream, pass in a MemoryStream you've already created. (Don't just create it inline in the call to PdfWriter.GetInstance - you'll want to be able to refer to it later.)
Then call ToArray() on the MemoryStream when you've finished writing to it to get a byte[]:
using (MemoryStream output = new MemoryStream())
{
PdfWriter wri = PdfWriter.GetInstance(doc, output);
// Write to document
// ...
return output.ToArray();
}
I haven't used iTextSharp, but I suspect some of these types implement IDisposable - in which case you should be creating them in using statements too.

Categories