I've developed a pdf file using itextsharp.
Pdf generation is working fine. After the pdf is created it's being downloaded.
My problem is when the user clicks on Generate PDF button , Pdf is generated and downloaded properly but postback doesn't occurs.
I want the postback to be occured because I want to Reset my Form after Pdf is generated that is Clear All Fields .
How Can I do this ?
Here is my code :
Method to Generate PDF :
public void GetPDF(string quote_num)
{
string url = FilesPath.Path_SaveFile + Session["empcd"].ToString() +"-Quotation.pdf";
Document disclaimer = new Document(PageSize.A4, 2, 2, 10, 10);
PdfWriter writer = PdfWriter.GetInstance(disclaimer, new FileStream(url, FileMode.Create));
writer.PageEvent = new myPDFpgHandler(quote_num);
disclaimer.SetMargins(70, 10, 60, 80);
disclaimer.Open();
GenerateQuotPDF getpdf = new GenerateQuotPDF();
disclaimer = getpdf.GetPDFparams(disclaimer,quote_num, Session["empcd"].ToString(),txt_contactperson.Text,txt_contact1.Text,txt_company.Text,txt_address.Text,ddl_gene_desc.SelectedItem.ToString(),ddl_canopy.SelectedItem.ToString(),ddl_gene_type.SelectedItem.ToString(),txt_rentalamount.Text,txt_hours.Text,txt_variable.Text,ddl_terms.SelectedItem.ToString(),txt_remarks.Text,txt_technical.Text,ddl_sign1.SelectedValue,ddl_sign2.SelectedValue,txt_designation.Text,DateTime.Now);
disclaimer.Close();
System.IO.FileInfo file = new System.IO.FileInfo(url);
if (file.Exists)
{
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(url);
Response.AddHeader("content-disposition", "attachment; filename=" + Session["empcd"].ToString() + "-Quotation.pdf");
Response.AddHeader("content-length", buffer.Length.ToString());
Response.ContentType = "application/pdf";
Response.BinaryWrite(buffer);
}
}
Generate PDF Button Code :
protected void btn_submit_Click(object sender, EventArgs e)
{
if (IsValidQuotation())
{
string newQuotNum = rental_quotations.GetNewQuotNumber();
rental_quotations.AddNewQuotation(newQuotNum, Session["empcd"].ToString(), ddl_gene_type.SelectedValue.ToString(), ddl_gene_desc.SelectedValue, ddl_canopy.SelectedValue, txt_company.Text, txt_address.Text, txt_contactperson.Text, txt_designation.Text, txt_contact1.Text, txt_contact2.Text, txt_rentalamount.Text, ddl_terms.SelectedValue, txt_hours.Text, txt_variable.Text, txt_remarks.Text,ddl_sign1.SelectedValue,ddl_sign2.SelectedValue,txt_technical.Text);
GetPDF(newQuotNum);
ClearAllFields(); //this is not working
}
}
Postback is occurring since the file is being created. Try the given solution. Your GetPDF(string quote_num) function is doing two tasks that you should break into two functions.
Creating the pdf document.
Downloading the pdf file after it is done.
Now, After you have created the document, you should clear the controls and then send the file as response. Therefore do it as follows:
Create pdf file.
public void CreatePDF(string quote_num)
{
string url = FilesPath.Path_SaveFile + Session["empcd"].ToString() +"-Quotation.pdf";
Document disclaimer = new Document(PageSize.A4, 2, 2, 10, 10);
PdfWriter writer = PdfWriter.GetInstance(disclaimer, new FileStream(url, FileMode.Create));
writer.PageEvent = new myPDFpgHandler(quote_num);
disclaimer.SetMargins(70, 10, 60, 80);
disclaimer.Open();
GenerateQuotPDF getpdf = new GenerateQuotPDF();
disclaimer = getpdf.GetPDFparams(disclaimer,quote_num, Session["empcd"].ToString(),txt_contactperson.Text,txt_contact1.Text,txt_company.Text,txt_address.Text,ddl_gene_desc.SelectedItem.ToString(),ddl_canopy.SelectedItem.ToString(),ddl_gene_type.SelectedItem.ToString(),txt_rentalamount.Text,txt_hours.Text,txt_variable.Text,ddl_terms.SelectedItem.ToString(),txt_remarks.Text,txt_technical.Text,ddl_sign1.SelectedValue,ddl_sign2.SelectedValue,txt_designation.Text,DateTime.Now);
disclaimer.Close();
}
Reset the controls.
ClearAllFields();
Send the file as response.
public void SendPDF(string url)
{
System.IO.FileInfo file = new System.IO.FileInfo(url);
if (file.Exists)
{
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(url);
Response.AddHeader("content-disposition", "attachment; filename=" + Session["empcd"].ToString() + "-Quotation.pdf");
Response.AddHeader("content-length", buffer.Length.ToString());
Response.ContentType = "application/pdf";
Response.BinaryWrite(buffer);
Response.End();
}
}
Note that I also added Response.End() to clear the buffer.
Related
I have this simple piece of code which I took from another question here with the same topic, corrupted PDF files.
I've tried to implement the described solution, along with other references, but have met no sucess yet.
Here are the two functions generating my example PDF:
private void ShowPdf (byte[] str)
{
var Response = HttpContext.Current.Response;
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=" + DateTime.Now);
Response.BinaryWrite(str);
Response.End();
Response.Flush();
Response.Clear();
}
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("Test bug") { Alignment = Element.ALIGN_CENTER };
Paragraph paragraph = new Paragraph("test.");
Phrase phrase = new Phrase("testnewline. \nnewline hapenned.");
Chunk chunk = new Chunk("Chucnk cauncuanocnaacoocsinasiocniocsanacsoi chunk.");
doc.Add(header);
doc.Add(paragraph);
doc.Add(phrase);
doc.Add(chunk);
doc.Close();
return output.ToArray();
}
}
Then at an request, I just consume it as in:
ShowPdf(CreatePDF2());
The problem is that this generates a file called "Response.pdf.pdf", which is corrupt and can't be opened.
How can I solve this problem?
Obs.: I am currently using iTextSharp 4.1.6
Try this for output variable,
FileStream output = new FileStream(Server.MapPath("MyFirstPDF.pdf"), FileMode.Create);
I have a web page in my website that allows me to download the chart from that page and add it to an excel sheet. However, a red x button with the words: "this image cannot currently be displayed" is shown in place of the chart. I have tried many solutions online but all of them show the same outcome.
Here are my codes:
protected void ExcelDl_Click(object sender, EventArgs e) {
string tmpChartName = "test2.jpg";
string imgPath = HttpContext.Current.Request.PhysicalApplicationPath + tmpChartName;
Chart1.SaveImage(imgPath);
string imgPath2 = Request.Url.GetLeftPart(UriPartial.Authority) + VirtualPathUtility.ToAbsolute("~/" + tmpChartName);
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment; filename=test.xls;");
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
string headerTable = #"<Table><tr><td><img src='" + imgPath2 + #"' \></td></tr></Table>";
Response.Write(headerTable);
Response.Write(sw.ToString());
Response.End();
}
Any form of help will be greatly appreciated. Also, do note that I have added the required codes in my Web.config.
We have tried your program and here it’s working fine. Excel downloaded along with image. I have installed in iis and tried with many client machine and it was working fine.
Not sure what’s going on your end. The problem might be wrong image path reference will cause this problem. Print image URL and make sure whether it is correct or not.
Alternate method: instead of using html tags inside the excel cell use XML closing method to render the image inside the excel cell.
Here I have added sample code for the Closed XML methods to render the image in excel. to use this code need to refer the following DLLs
1. ClosedXML.dll
2. WindowsCore.dll
3. DocumentFormat.OpenXML.dll
4. PresentationCore.dll
Reference Link for Closed XML methods: https://closedxml.codeplex.com/
using (XLWorkbook wb = new XLWorkbook())
{
IXLWorksheet WorkSheet = new IXLWorksheet();
string LogoPath = Server.MapPath("~/App_Themes/Images/logonew.png");
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(LogoPath);
if (bitmap != null)
{
var stream = new System.IO.MemoryStream();
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
if (stream != null)
{
stream.Position = 0;
XLPicture pic = new XLPicture
{
NoChangeAspect = true,
NoMove = true,
NoResize = true,
ImageStream = stream,
Name = "Logo",
EMUOffsetX = 4,
EMUOffsetY = 6
};
XLMarker fMark = new XLMarker
{
ColumnId = 1,
RowId = 1
};
pic.AddMarker(fMark);
WorkSheet.AddPicture(pic);
}
}
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;filename=test.xls");
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
MyMemoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}
Please check and let me know your comments.
This is my code which is used in a wcf service. It successfully generates the PDF, but after generating the document, the folder in which the PDF is generated gives the error: "access is denied"
The PDF is closed for the website, but for the continuous web service it is not closed.
string r = builder.ToString();
string pdfname = Fuhre + "_" + ProtokolType + "_" + GeraeteNr + "_" + r;
PdfWriter.GetInstance(document, new FileStream(#"C:\inetpub\wwwroot\protokoll_pdfs\"+pdfname+".pdf",FileMode.Create));
document.Open();
WebClient wc = new WebClient();
string htmlText = html;
//Response.Write(htmlText);
List<IElement> htmlarraylist = HTMLWorker.ParseToList(new StringReader(htmlText), null);
for (int k = 0; k < htmlarraylist.Count; k++)
{
document.Add((IElement)htmlarraylist[k]);
}
pdflink1 = pdfname + ".pdf";
htmlpdflink =""+pdflink1;
document.Close();
You need to be careful to dispose of everything.
using(var filesStream = new FileStream())
{
using(PdfWriter wri = PdfWriter.GetInstance(doc, fileStream))
{
...
}
}
There are a few other objects (Stream, Document) you may want to close. A sample of how to perform the operation is shown below.
FileStream stream = new FileStream(filePath, FileMode.CreateNew);
Document doc = new Document(PageSize.A4, 24, 24, 24, 24);
PdfWriter writer = PdfWriter.GetInstance(doc, stream);
doc.Open();
//PDF writing operations here
writer.Flush();
doc.Close();
writer.Close();
stream.Close();
You want to serve a file to a browser and/or you want to save the file on disk.
In that case, you would benefit from creating the file in memory and then send the bytes to the browser as well as to a file on disk. This is explained in the answer to the following question: Pdf file not loading properly created by the servlet
The answer mentioned above is written in Java, so you'll have to adapt it.
You can do so by looking at other examples. For instance: Create PDF in memory instead of physical file
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();
}
Now you can write the pdfBytes to the Response object in your web application:
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();
}
And you can reuse the bytes to write them to a File: Can a Byte[] Array be written to a file in C#?
File.WriteAllBytes(string path, byte[] bytes)
If the problem persist, then you know that it isn't caused by iTextSharp, because iTextSharp merely produces the bytes.
In addition to what everyone else said, I strongly recommend you break each process into multiple sections that don't interact and aren't even aware of each other. Then test each section independently as much as possible. For instance:
private void makePDF( filePath )
{
//Create the PDF
}
private void main()
{
//Make the PDF
makePDF( "test.pdf" );
//If this line fails then your makePDF code has an open handle
File.Delete( "test.pdf" );
}
Then continue:
private void makePDF( filePath )
{
//Create the PDF
}
private void emailPDF( filePath )
{
//Email the PDF
}
private void main()
{
//Make the PDF
makePDF( "test.pdf" );
emailPDF( "test.pdf" );
//If this line fails now then your emailPDF code has an open handle
File.Delete( "test.pdf" );
}
The important part if that you don't try 500 things all at once because that leads to "something is locking my file but I don't know what".
I've a handler in asp.net app. When there comes some kind of request I want user to get download window, where I put PDF stream. I don't want PDF to be saved in memory.
I have the following code, but it fails to open, says pdf file was demaged and couldn't open it.
tell me other way to achieve my goal if you think mine is not good.
MemoryStream stream = new MemoryStream();
CreatePFD(T.Text, stream);
context.Response.Write(stream);
context.Response.ContentType = "application/pdf";
context.Response.AddHeader("content-disposition", "attachment; filename=" + "Nots__Saved__FIle__fileName.pdf");
Now I have this code:
Document Doc = new Document(PageSize.A4, 80, 50, 30, 65);
System.IO.Stream outputStream = new System.IO.FileStream(#"C:\inetpub\wwwroot\c\wefwe.pdf", System.IO.FileMode.OpenOrCreate);
PdfWriter.GetInstance(Doc, outputStream);
Doc.Open();
List<IElement> htmlarraylist = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(new StringReader(T.Text), null);
for (int k = 0; k < htmlarraylist.Count; k++)
{
Doc.Add((IElement)htmlarraylist[k]);
}
outputStream.CopyTo(context.Response.OutputStream);
Doc.Close();
context.Response.ContentType = "application/pdf";
context.Response.AddHeader("content-disposition", "attachment; filename=" + "Nots__Saved__FIle__fileName.pdf");
when i save pdf, the file is correct...
but when I get response the file is in correct. demaged...
You need to rewind the stream by setting stream.Position = 0.
Also, Response.Write(stream) will just print stream.ToString().
Instead, you should call stream.CopyTo(Response.OutputStream).
I am trying to download multiple pdf's as attachments in my asp.net application.I have created some templates and filling values using pdfstamper(itextsharp). I am able to fill the values but not able to download.
private void FillForm(string path, DataTable BridgeValues, DataTable Comments, DataTable Maintenance,string Newfilename)
{
try
{
string pdfTemplate = path;
string newFile = Newfilename;
string Pathser = "";
if (!System.IO.Directory.Exists(Server.MapPath(#"~/PDF/")))
{
System.IO.Directory.CreateDirectory(Server.MapPath(#"~/PDF/"));
}
if (Directory.Exists(Server.MapPath(#"~/PDF/")))
{
Pathser = Server.MapPath(#"~/PDF/" + Newfilename);
}
System.IO.MemoryStream mStream = new System.IO.MemoryStream();
// create a new PDF reader based on the PDF template document
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(Pathser, FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
DataColumn dc = null;
for (int i = 0; i < BridgeValues.Columns.Count - 1; i++)
{
dc = BridgeValues.Columns[i];
pdfFormFields.SetField(dc.ColumnName.ToString(), BridgeValues.Rows[0][dc].ToString());
}
pdfStamper.FormFlattening = true;
// close the pdf
pdfStamper.Close();
////Response.ContentType = "application/octet-stream";
Response.ContentType = "application/pdf";
////Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf");
Response.AddHeader("Content-Disposition", "attachment; filename=" + Newfilename + "");
////Response.BinaryWrite(mStream.ToArray());
Response.TransmitFile(Server.MapPath(("~/PDF/"+ Newfilename)));
Response.Clear();
Response.End();
}
catch (System.Threading.ThreadAbortException lException)
{
// do nothing
}
}
First time I tried to create one pdf ,it worked but later when I tried to download multiple files it gave an execption.
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.
I don't think you can download multiple files by making one request and returning a collection from the action. I would suggest that it you need to allow user to download multiple files you ZIP them and stream the archive down to the browser.
Here is an example of zipping multiple files: http://devpinoy.org/blogs/keithrull/archive/2008/01/25/how-to-create-zip-files-in-c-with-sharpziplib-ziplib.aspx