bogorman
asked on
Script can generate corrupted pdf file
The attached coding generates a pdf file. Unfortunately sometimes the file is corrupted - it appears to have a size of zero bytes and I cannot delete it using FileZilla or Internet Explorer 7 (via FTP).
Have been in touch with the web hosters and they say that:
"It appears it may have to be the way the file is betting created. For some reason it corrupts the permissions on the file, and they look like they're right, but they really are not. You may want to look over the way the file is being created."
Can anyone suggest a solution?
Have been in touch with the web hosters and they say that:
"It appears it may have to be the way the file is betting created. For some reason it corrupts the permissions on the file, and they look like they're right, but they really are not. You may want to look over the way the file is being created."
Can anyone suggest a solution?
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using iTextSharp.text;
using iTextSharp.text.pdf;
using MySql.Data.MySqlClient;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Document doc = new Document(PageSize.A4, 12, 15, 30, 0);
string pdfFileLocation = @"D:\inetpub\DomainID54847\ConvertToPdf\Test.pdf";
PdfWriter.GetInstance(doc, new System.IO.FileStream(pdfFileLocation, System.IO.FileMode.Create));
//PdfWriter.GetInstance(doc, new System.IO.FileStream("Test.pdf", System.IO.FileMode.Create));
doc.Open();
//PdfPTable table = new PdfPTable(2);
PdfPTable table = new PdfPTable(3);
//actual width of table in points
table.TotalWidth = 580f;
//fix the absolute width of the table
table.LockedWidth = true;
//relative col widths in proportions - 1/3 and 2/3
//float[] widths = new float[] { 1f, 2f };
//relative widths 1/3 1/3 1/3
float[] widths = new float[] { 1f, 1f, 1f };
table.SetWidths(widths);
table.HorizontalAlignment = 0;
//leave a gap before and after the table
//table.SpacingBefore = 42f;
//table.SpacingAfter = 30f;
table.DefaultCell.Border = 0;
table.DefaultCell.PaddingLeft = 5;
float TopPad = 12.5F;
table.DefaultCell.PaddingTop = TopPad;
table.DefaultCell.PaddingBottom = 30;
PdfPCell cell = new PdfPCell();
cell.FixedHeight = 100;
//cell.Colspan = 2;
cell.Colspan = 3;
cell.Border = 0;
cell.HorizontalAlignment = 1;
//table.AddCell(cell); NB MAY HAVE TO UNQUOTE THIS!!!!!
BaseFont bfTimes = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);
Font times = new Font(bfTimes, 10);
int UserID;
if (!int.TryParse(Request.QueryString["UserID"], out UserID))
{
Console.WriteLine("User ID not passed to page"); // Handle error
}
// Create the select command string
// The school name is reduced in length to 38 characters to avoid it spilling over to two lines on the label
string cmdstring = "select fldContact, Name, If(trim(addr1)='','. ', addr1) as ad1, If(trim(addr2)='','. ',addr2) as ad2," +
"If(trim(addr3)='','. ',addr3) as ad3, If(trim(addr4)='','. ',addr4) as ad4, If(trim(addr5)='','. ',addr5) as ad5 " +
"FROM (" +
"select fldContact, LEFT(trim(fldName),38) AS Name, fldADDR1, fldADDR2, fldTOWN, fldCOUNTY, fldPOSTCODE, ad," +
"REPLACE(SUBSTRING(SUBSTRING_INDEX(ad, char(26), 1)," +
"LENGTH(SUBSTRING_INDEX(ad, char(26), 1 -1)) + 1)," +
"char(26), '') as addr1," +
"REPLACE(SUBSTRING(SUBSTRING_INDEX(ad, char(26), 2)," +
"LENGTH(SUBSTRING_INDEX(ad, char(26), 2 -1)) + 1)," +
"char(26), '') as addr2," +
"REPLACE(SUBSTRING(SUBSTRING_INDEX(ad, char(26), 3)," +
"LENGTH(SUBSTRING_INDEX(ad, char(26), 3 -1)) + 1)," +
"char(26), '') as addr3," +
"REPLACE(SUBSTRING(SUBSTRING_INDEX(ad, char(26), 4), " +
"LENGTH(SUBSTRING_INDEX(ad, char(26), 4 -1)) + 1)," +
"char(26), '') as addr4," +
"REPLACE(SUBSTRING(SUBSTRING_INDEX(ad, char(26), 5)," +
"LENGTH(SUBSTRING_INDEX(ad, char(26), 5 -1)) + 1)," +
"char(26), '') as addr5 " +
"from (" +
"SELECT fldContact, fldName, fldADDR1, fldADDR2, fldTOWN, fldCOUNTY, fldPOSTCODE," +
"concat_ws(char(26),nullif(trim(fldADDR1),'')," +
"nullif(trim(fldADDR2),'')," +
"nullif(trim(fldTOWN),'')," +
"nullif(trim(fldCOUNTY),'')," +
"nullif(trim(fldPOSTCODE),'')) as ad " +
"FROM tblschools RIGHT JOIN tblselectedschools ON tblschools.fldSCHOOL_ID = tblselectedschools.fldSCHOOL_ID " +
"WHERE tblselectedschools.fldUserID = " + UserID.ToString() + " AND tblselectedschools.fldSelected = 1 ORDER BY fldName, fldPOSTCODE) as v" +
") as v1;";
// Create the Connectionstring
// PersistSecurityInfo = false means that the password is not displayed in the
// connectionstring of the MySqlCommand.
//
MySqlConnectionStringBuilder connBuilder = new MySqlConnectionStringBuilder();
connBuilder.Database ="xxx";
connBuilder.Password ="xxxx";
connBuilder.PersistSecurityInfo = false;
connBuilder.Server = "xxxxxx";
connBuilder.UseCompression = true;
connBuilder.UserID = "xxxxx";
// Create the connection
MySqlConnection conn = new MySqlConnection(connBuilder.ConnectionString);
MySqlCommand comm = new MySqlCommand(cmdstring, conn);
//comm.Parameters.AddWithValue("userID", 2);
comm.Parameters.AddWithValue("selected", 1);
//comm.Parameters.AddWithValue("userID", 2);
//comm.Parameters.AddWithValue("selected", 1);
try {
// Open and execute the command
conn.Open();
using (MySqlDataReader reader = comm.ExecuteReader())
{
while (reader.Read())
{
string text = string.Format(
"{0}\r\n{1}\r\n{2}\r\n{3}\r\n{4}\r\n{5}\r\n{6}",
reader["fldContact"],
reader["Name"],
reader["ad1"],
reader["ad2"],
reader["ad3"],
reader["ad4"],
reader["ad5"]);
Phrase myPhrase = new Phrase(text, times);
table.AddCell(myPhrase);
}
}
doc.Add(table);
doc.Close();
} finally {
conn.Dispose();
comm.Dispose();
}
}
protected void Button1_Click(object sender, EventArgs e)
{
}
}
ASKER
Thanks for your quick reply.
When I try to build, I get the error:
"iTextSharp.text.document. close" is inaccessible due to its protection level
I have altered the final coding as you suggest. Think it's right:
doc.Add(table);
//doc.Close();
} finally {
doc.close();
conn.Dispose();
comm.Dispose();
}
}
In fact intellisense displays this error if I hover over the doc.Close(); line.
When I try to build, I get the error:
"iTextSharp.text.document.
I have altered the final coding as you suggest. Think it's right:
doc.Add(table);
//doc.Close();
} finally {
doc.close();
conn.Dispose();
comm.Dispose();
}
}
In fact intellisense displays this error if I hover over the doc.Close(); line.
Make sure Close() has an uppercase C, the code you've posted is lowercase, which could be an overloaded public method (which would explain the compile error)
ASKER
Yes, I noticed that after I send you the coding. Unfortunately, when I change the c to uppercase I still get the error via intellisense.
Any other ideas?
Any other ideas?
ASKER
Any further thoughts on this. I assume the syntax has to be different if I move the Close statement.
One thing I thought of. If the page attempts to create the pdf where there is one already present, it has to overwrite the earlier copy. Should I delete this first? If so, how can I in c sharp detect whether the file is present and, if so, delete it? Could this cause the corruption of the file?
One thing I thought of. If the page attempts to create the pdf where there is one already present, it has to overwrite the earlier copy. Should I delete this first? If so, how can I in c sharp detect whether the file is present and, if so, delete it? Could this cause the corruption of the file?
ASKER
Sorry. I may have made a mistake.
I now find it builds without error - maybe I forgot to save the project before building - but it still creates a zero-byte file which I cannot delete. Also, I get an error when opening the page:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[IOException: The document has no pages.]
iTextSharp.text.pdf.PdfPag es.WritePa geTree() +1287
iTextSharp.text.pdf.PdfWri ter.Close( ) +75
iTextSharp.text.pdf.PdfDoc ument.Clos e() +138
iTextSharp.text.Document.C lose() +101
_Default.Page_Load(Object sender, EventArgs e) +1118
System.Web.Util.CalliHelpe r.EventArg FunctionCa ller(IntPt r fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEvent HandlerDel egateProxy .Callback( Object sender, EventArgs e) +35
System.Web.UI.Control.OnLo ad(EventAr gs e) +99
System.Web.UI.Control.Load Recursive( ) +50
System.Web.UI.Page.Process RequestMai n(Boolean includeStagesBeforeAsyncPo int, Boolean includeStagesAfterAsyncPoi nt) +627
Would appreciate any further help you can give me on this.
I now find it builds without error - maybe I forgot to save the project before building - but it still creates a zero-byte file which I cannot delete. Also, I get an error when opening the page:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[IOException: The document has no pages.]
iTextSharp.text.pdf.PdfPag
iTextSharp.text.pdf.PdfWri
iTextSharp.text.pdf.PdfDoc
iTextSharp.text.Document.C
_Default.Page_Load(Object sender, EventArgs e) +1118
System.Web.Util.CalliHelpe
System.Web.Util.CalliEvent
System.Web.UI.Control.OnLo
System.Web.UI.Control.Load
System.Web.UI.Page.Process
Would appreciate any further help you can give me on this.
Ah, what appears to be happening is that iTextSharp can't write an empty document (it doesn't conform to the PDF spec, as far as I remember), so it throws the exception when attempting to close the document (and the underlying stream).
Hence the underlying FileStream remains open, with a read lock (which is the default lock when no FileShare parameter is passed to the FileStream constructor) maintained by IIS.
So, first you need to fix the code creating the PDF. However, to prevent the locking issue, you need to make sure the underlying stream is closed, even if the PDF can't be created.
Hence the underlying FileStream remains open, with a read lock (which is the default lock when no FileShare parameter is passed to the FileStream constructor) maintained by IIS.
So, first you need to fix the code creating the PDF. However, to prevent the locking issue, you need to make sure the underlying stream is closed, even if the PDF can't be created.
protected void Page_Load(object sender, EventArgs e)
{
Document doc = new Document(PageSize.A4, 12, 15, 30, 0);
string pdfFileLocation = @"D:\inetpub\DomainID54847\ConvertToPdf\Test.pdf";
System.IO.FileStream docStream = new System.IO.FileStream(pdfFileLocation, System.IO.FileMode.Create);
PdfWriter.GetInstance(doc, docStream);
// Snip
try {
// Snip
doc.Add(table);
// Remove here
// doc.Close();
} finally {
// Close should always be called now
// If the PDF has no contents, an exception will not be caught,
// but at least the file will be closed (and unlocked)
try {
doc.Close();
} finally{
// Also make sure the underlying stream is closed
// You could delete the file here if it's empty
docStream.Close();
}
conn.Dispose();
comm.Dispose();
}
}
ASKER
Thanks very much. Will try that.
Also, is it advisable to delete the 'old' pdf file first before recreating the new one? If so, can you suggest a coding to check if the file is present and, if so, delete it?
Also, is it advisable to delete the 'old' pdf file first before recreating the new one? If so, can you suggest a coding to check if the file is present and, if so, delete it?
Deleting a file before it's created is an option, however it does mean that a valid file may be overwritten which may not be desired. Personally, I would only delete the file if the PDF generation fails.
As for determining if the file exists, you can use the FileInfo class, which not only will tell you if the file exists, but the size as well as various other information.
As for determining if the file exists, you can use the FileInfo class, which not only will tell you if the file exists, but the size as well as various other information.
System.IO.FileInfo fi = new System.IO.FileInfo(fileName);
if (fi.Exists && fi.Length == 0){
// File already exists, but is empty
// Do stuff
}
ASKER
Think you have solved my problem and the pdf does not seem to be being corrupted now.
However, I would like to have a button on the form on the webpage to open the pdf. At present, the html is listed below.
The ViewPrintPdf function is included in the cs file
protected void ViewPrintPdf(object sender, EventArgs e)
{
Response.Redirect(pdfFileL ocation, true);
}
The problem is that both buttons close the form. I assume that this is due to the action of the form being set to "../Home.asp" and any both buttons act as submit buttons (or am I talking nonsense?)
What I would like to do is for btnViewPrintPdf to open the pdf in a popup window and the other button to redirect the page to the home page.
I realise this is another question, though related to my original one. If you would prefer me to assign the points to you at this stage and post another question, I will quite understand.
However, I would like to have a button on the form on the webpage to open the pdf. At present, the html is listed below.
The ViewPrintPdf function is included in the cs file
protected void ViewPrintPdf(object sender, EventArgs e)
{
Response.Redirect(pdfFileL
}
The problem is that both buttons close the form. I assume that this is due to the action of the form being set to "../Home.asp" and any both buttons act as submit buttons (or am I talking nonsense?)
What I would like to do is for btnViewPrintPdf to open the pdf in a popup window and the other button to redirect the page to the home page.
I realise this is another question, though related to my original one. If you would prefer me to assign the points to you at this stage and post another question, I will quite understand.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Close(object sender, EventArgs e)
{
Response.BufferOutput = true;
Response.Redirect("../Home.asp");
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>LIFEnet Label Printing Utility</title>
</head>
<body>
<form id="form1" runat="server" action="../Home.asp">
<div>
<br />
<table bordercolor="#ffffff" style="width: 672px" align="center">
<tr>
<td colspan="3" style="font-weight: bold; font-size: 18pt; width: 696px; font-family: Arial; text-align: center">
Lifenet Label Printing Utility<br />
<br />
</td>
</tr>
<tr>
<td colspan="3" style="font-size: 20px; width: 696px; font-family: Arial; text-align: center">
Your labels are ready to print.<br />
<br />
<br />
<br />
</td>
</tr>
<tr>
<td colspan="3" style="width: 696px; text-align: center">
<asp:Button ID="btnViewPrintPdf" runat="server" onclick="ViewPrintPdf" Text="View/Print Your Labels" Height="40px" Width="304px" />
<asp:Button ID="btnClose" runat="server" onclick="Close" Height="40px" Text="Close and Return to LIFEnet Homepage" Width="304px" /></td>
</tr>
</table>
<br />
<br />
</div>
</form>
</body>
</html>
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi oobayly,
Thanks so much for your help. Have been struggling to find the solution to the corruption of the pdf file for weeks. You further advice on the ViewPrint button is most helpful and works fine.
Regards
Brian
Thanks so much for your help. Have been struggling to find the solution to the corruption of the pdf file for weeks. You further advice on the ViewPrint button is most helpful and works fine.
Regards
Brian
See what happens if you place doc.Close() in the finally block
Open in new window