save Pdf File in the particular folder instead of downloading - c#

I am doing html to pdf file . Its Downloading instantly . I dont want download instantly. i want to save the file in my project folder once converted.
My C# Code
string html ="<table><tr><td>some contents</td></tr></table>";
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=WelcomeLetter.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
StringReader sr = new StringReader(table);
Document ResultPDF = new Document(iTextSharp.text.PageSize.A4, 25, 10, 20, 30);
PdfPTable Headtable = new PdfPTable(7);
Headtable.TotalWidth = 525f;
Headtable.LockedWidth = true;
Headtable.HeaderRows = 5;
Headtable.FooterRows = 2;
Headtable.KeepTogether = true;
HTMLWorker htmlparser = new HTMLWorker(ResultPDF);
PdfWriter.GetInstance(ResultPDF, Response.OutputStream);
ResultPDF.Open();
htmlparser.Parse(sr);
ResultPDF.Close();
Response.Write(ResultPDF);
Response.End();

For saving pdf file locally in your project folder you can use FileStream class like this.
FileStream stream = new FileStream(filePath, FileMode.Create);//Here filePath is path of your project folder.
Now use this stream instead of using Response.OutputStream when you create instance of PdfWriter object.
PdfWriter.GetInstance(ResultPDF, stream);
Now do not use Responce.Write as you don't want to download your file.And close your stream at end.
stream.Close();

I'm going to combine everyone's answer into one that you should be able to drop in and use. If this works, I would accept Manish Parakhiya's answer because that had the most important part.
First, I'm going to assume you are using a recent version of iTextSharp. I think 5.5.5 is the most recent version. Second, because of this, I'm going to restructure your code a bit in order to use the using pattern. If you're stuck on an older obsolete unsupported version like 4.1.6 you'll need to re-adjust.
Almost every tutorial out there shows you that you can bind directly the Response.OutputStream. This is 100% valid but I would argue that it is also a really bad idea. Instead, bind to a more generic MemoryStream. This makes debugging much easier and your code will port and adapt that much easier.
The below code includes comments about each of the changes and what things are actually doing. The top section is all about creating a PDF from a string of HTML. The bottom actually does something with it, including writing it to disk and/or streaming it to a browser.
//Will hold our PDF eventually
Byte[] bytes;
//HTML that we want to parse
string html = "<table><tr><td>some contents</td></tr></table>";
//Create a MemoryStream to write our PDF to
using (var ms = new MemoryStream()) {
//Create our document abstraction
using (var ResultPDF = new Document(iTextSharp.text.PageSize.A4, 25, 10, 20, 30)) {
//Bind a writer to our Document abstraction and our stream
using (var writer = PdfWriter.GetInstance(ResultPDF, ms)) {
//Open the PDF for writing
ResultPDF.Open();
//Parse our HTML using the old, obsolete, not support parser
using (var sw = new StringWriter()) {
using (var hw = new HtmlTextWriter(sw)) {
using (var sr = new StringReader(html)) {
using (var htmlparser = new HTMLWorker(ResultPDF)) {
htmlparser.Parse(sr);
}
}
}
}
//Close the PDF
ResultPDF.Close();
}
}
//Grab the raw bytes of the PDF
bytes = ms.ToArray();
}
//At this point, the bytes variable holds a valid PDF file.
//You can write it disk:
System.IO.File.WriteAllBytes("your file path here", bytes);
//You can also send it to a browser:
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=WelcomeLetter.pdf");
Response.BinaryWrite(bytes);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
//Never do the next line, it doesn't do what you think it does and actually produces corrupt PDFs
//Response.Write(ResultPDF); //BAD!!!!!!
Response.End();

string tempDirectory = Session.SessionID.ToString();
string location = Path.Combine(Server.MapPath(
WebConfigurationManager.AppSettings["PathSet"].ToString()), tempDirectory);
if (!Directory.Exists(location))
{
Directory.CreateDirectory(location);
}
string fileName="abc.pdf";
filePath = Path.Combine(location, fileName);

Related

Send PDF to the browser rather than saving to the server - ASP.NET iText 7 C# Web Forms

this is my first time posting on SO
I have been using iText 7 so users of my web app can generate a pdf of a document.
I would like the document sent to the browser so either it gets saved to the user Downloads folder or the user can choose where to save it with the browser save dialog box.
However, all the C# examples I have found require a hard-coded path & file name, so it gets saved on the server rather than client machines.
I have been researching this for a few days now and floundering around with solutions, this is what I have:
public void mtdCreatePDF()
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=print.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
var stream = new MemoryStream();
var writer = new PdfWriter(stream);
var pdf = new PdfDocument(writer);
var document = new Document(pdf);
document.Add(new Paragraph("Hello world!"));
document.Close();
Response.Write(document);
Response.End();
}
This creates print.pdf in browser Downloads folder, but the file is corrupt.
I would be grateful if someone could point out where I am going wrong, the majority of articles in this regard relate to the older itextsharp, and the iText 7 examples have hard-coded file paths and file names.
I have found one possible solution that looks good, but unfortunately it is in Java. I've been floundering around for ages trying to convert it to C#, but I don't know any Java so it's turned into a pig's breakfast. This is the Java solution:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(baos));
Document doc = new Document(pdfDoc);
doc.add(new Paragraph("Hello world!"));
doc.close();
// setting some response headers
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
// setting the content type
response.setContentType("application/pdf");
// the contentlength
response.setContentLength(baos.size());
// write ByteArrayOutputStream to the ServletOutputStream
OutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();
Any help would be greatly appreciated.
Thank you
This solution seems to be working perfectly.
public void mtdCreatePDF()
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=print.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
var stream = new MemoryStream();
var writer = new PdfWriter(stream);
var pdf = new PdfDocument(writer);
var document = new Document(pdf);
document.Add(new Paragraph("Hello world!"));
document.Close();
Response.BinaryWrite(stream.ToArray());
Response.End();
}

How to store Generated pdf on deployed website with Itext

I am trying to write to a pdf and send it in an email.I am able to implement this on my local machine. The problem is when I deploy to azure I am not sure where to store the pdf . I have seen one question regarding this
and tried this solution from stackoverflow -
Does iText (any version) work on Windows Azure websites?.
var path = Server.MapPath("test.pdf");
FileInfo dest = new FileInfo(path);
var writer = new PdfWriter(dest);
var pdf = new PdfDocument(writer);
var document = new Document(pdf);
document.Add(new Paragraph("hello world"));
document.Close();
I get an error
Could not find a part of the path
'D:\home\site\wwwroot\Email\test.pdf'.
Try to create the Pdf in memory and stream the content to the asp.net output stream.
Document document = new Document(PageSize.A4);
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
document.Open();
document.NewPage();
...
...
document.Close();
Response.Clear();
Response.ContentType = "application/pdf";
byte[] pdfBytes = ms.ToArray();
Response.AppendHeader("Content-Length", pdfBytes.Length.ToString());
Response.OutputStream.Write(pdfBytes, 0, (int)pdfBytes.Length);
I suppose your issue is related with the file path.
If I use the path like Server.MapPath("Azure_Example1.pdf"), I also get the same error as you.
I suggest you could try to use the relative path like Server.MapPath("~/Azure_Example1.pdf"). The '~/' points to the project root directory.
You could also set a break point to check the value of path by using remote debugging.
I have created a simple demo, it works fine on my side. You could refer to.
Install the iTextSharp 5.5.13 nuget package in Manage Nuget Packages.
Use the following code:
var path = Server.MapPath("~/Azure_Example1.pdf");
FileInfo dest = new FileInfo(path);
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
Document doc = new Document();
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
doc.Add(new Paragraph("Hello World")); //change content in pdf
doc.Close();
Finally, you could see the pdf file has been stored in root project directory.

Save pdf on a particular location using C#

Here is my C# Code :
protected void Button1_Click(object sender, EventArgs e)
{
string attachment = "attachment; filename=" + Session["pdf_name"] + ".pdf";
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/pdf";
StringWriter s_tw = new StringWriter();
HtmlTextWriter h_textw = new HtmlTextWriter(s_tw);
Label1.Style.Add("font-size", "16pt");
Label2.Style.Add("font-size", "16pt");
Label3.Style.Add("font-size", "16pt");
h_textw.AddStyleAttribute("font-size", "8pt");
h_textw.AddStyleAttribute("color", "Black");
Panel1.RenderControl(h_textw);
Document doc = new Document();
PdfWriter.GetInstance(doc, Response.OutputStream);
doc.Open();
StringReader s_tr = new StringReader(s_tw.ToString());
HTMLWorker html_worker = new HTMLWorker(doc);
html_worker.Parse(s_tr);
doc.Close();
Response.Write(doc);
}
I want to save this pdf in this Path "H:\new\web\pdf_filename.pdf"
I am using ASP.Net C#.
You cannot specify where on the client machine the downloaded file will be saved.
If you want that type of functionality, you will need to run a plugin in the browser clientside that has access to the local file system.
The browser will take the filename you specify in your attachment header value as a suggestion, but even that can be overridden by the user when he actually saves it.
If you want to save it on the server, you only have to save it somewhere local (to the server) using any of the file-related methods or types.
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(#"H:\new\web\pdf_filename.pdf", FileMode.Create));
try and see if this work, please make sure your authentication type is allow user to access that folder. Not everyone map H drive to same network path,

Save the generated pdf directly to the server directory folder without user prompt

A friend of mine gave me this task so I can learn advance programming a little bit easier. I am currently doing convertion of an html page to pdf using itext sharp and email the pdf as an attachement. My idea is to save the pdf first to the server machine in the folder name ToBeEmailedPDF folder before using it as an email attachment. The thing that bothers me is that this dialog as what you can see in the picture shows up using the code that I have below.
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);
pnlPDF.RenderControl(hw); // pnlPDF contains the html contents to be converted to pdf
string htmlDisplayText = sb.ToString();
Document document = new Document();
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
StringReader se = new StringReader(htmlDisplayText);
HTMLWorker obj = new HTMLWorker(document);
document.Open();
obj.Parse(se);
// step 5: we close the document
document.Close();
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=report.pdf");
Response.ContentType = "application/pdf";
Response.Buffer = true;
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
Response.OutputStream.Flush();
Response.End();
I know many of you out there knows a better way or know how to solve my problem. Please help me. Thank you!
There is big difference between client-side and server-side.
Response class can output contents to client machine, if you need to save file on server use something like File.WriteAllBytes (msdn) method
What you are trying to achieve is impossible for security reasons. Only the user can decide where he wants the attachment to be saved. Imagine if this was possible: you would then be able to save any kind of viruses into any kind of folders on the user's computer. As an alternative to showing the Save dialog you could open the PDF inline:
Response.AddHeader("Content-Disposition", "inline; filename=report.pdf");
You can save it using the following code:
PdfWriter.GetInstance(pdfDoc, new FileStream(context.Server.MapPath("~") + "/PDF/" + reportName + ".pdf", FileMode.Create));

Need help with creating PDF from HTML using itextsharp

I'm trying to crate a PDF out of a HTML page. The CMS I'm using is EPiServer.
This is my code so far:
protected void Button1_Click(object sender, EventArgs e)
{
naaflib.pdfDocument(CurrentPage);
}
public static void pdfDocument(PageData pd)
{
//Extract data from Page (pd).
string intro = pd["MainIntro"].ToString(); // Attribute
string mainBody = pd["MainBody"].ToString(); // Attribute
// makae ready HttpContext
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/pdf";
// Create PDF document
Document pdfDocument = new Document(PageSize.A4, 80, 50, 30, 65);
//PdfWriter pw = PdfWriter.GetInstance(pdfDocument, HttpContext.Current.Response.OutputStream);
PdfWriter.GetInstance(pdfDocument, HttpContext.Current.Response.OutputStream);
pdfDocument.Open();
pdfDocument.Add(new Paragraph(pd.PageName));
pdfDocument.Add(new Paragraph(intro));
pdfDocument.Add(new Paragraph(mainBody));
pdfDocument.Close();
HttpContext.Current.Response.End();
}
This outputs the content of the article name, intro-text and main body.
But it does not pars HTML which is in the article text and there is no layout.
I've tried having a look at http://itextsharp.sourceforge.net/tutorial/index.html without becomming any wiser.
Any pointers to the right direction is greatly appreciated :)
For later versions of iTextSharp:
Using iTextSharp you can use the iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList() method to create a PDF from HTML.
ParseToList() takes a TextReader (an abstract class) for its HTML source, which means you can use a StringReader or StreamReader (both of which use TextReader as a base type). I used a StringReader and was able to generate PDFs from simple mark up. I tried to use the HTML returned from a webpage and got errors on all but the simplist pages. Even the simplist webpage I retrieved (http://black.ea.com/) was rendering the content of the page's 'head' tag onto the PDF, so I think the HTMLWorker.ParseToList() method is picky about the formatting of the HTML it parses.
Anyway, if you want to try here's the test code I used:
// Download content from a very, very simple "Hello World" web page.
string download = new WebClient().DownloadString("http://black.ea.com/");
Document document = new Document(PageSize.A4, 80, 50, 30, 65);
try {
using (FileStream fs = new FileStream("TestOutput.pdf", FileMode.Create)) {
PdfWriter.GetInstance(document, fs);
using (StringReader stringReader = new StringReader(download)) {
ArrayList parsedList = HTMLWorker.ParseToList(stringReader, null);
document.Open();
foreach (object item in parsedList) {
document.Add((IElement)item);
}
document.Close();
}
}
} catch (Exception exc) {
Console.Error.WriteLine(exc.Message);
}
I couldn't find any documentation on which HTML constructs HTMLWorker.ParseToList() supports; if you do please post it here. I'm sure a lot of people would be interested.
For older versions of iTextSharp:
You can use the iTextSharp.text.html.HtmlParser.Parse method to create a PDF based on html.
Here's a snippet demonstrating this:
Document document = new Document(PageSize.A4, 80, 50, 30, 65);
try {
using (FileStream fs = new FileStream("TestOutput.pdf", FileMode.Create)) {
PdfWriter.GetInstance(document, fs);
HtmlParser.Parse(document, "YourHtmlDocument.html");
}
} catch(Exception exc) {
Console.Error.WriteLine(exc.Message);
}
The one (major for me) problem is the HTML must be strictly XHTML compliant.
Good luck!

Categories