I'm creating PDF invoices in a C# MVC application that I'm attaching to an email and sending, ideally, once the email is sent I'd like to delete the invoice to free up server space and improve privacy/security. I've written code to do it but it fails 50% of the time because the file is locked by another process (I'm not sure if it's the create/write process that's locking it or the email send). I'm sending the email asynchronously (i.e. the code to delete doesn't execute until the email has sent).
I'd appreciate some tips on how to handle this problem. I could run a job to clean up old files but I'd prefer to clean them up as I go...
I forgot to mention I am using iTextSharp to generate the PDF - the crux of it is this code is used to generate the final invoice (I am able to delete the list of files passed in as a param without drama):
/// <summary>
/// http://stackoverflow.com/questions/4276019/itextsharp-pdfcopy-use-examples
/// </summary>
/// <param name="fileNames"></param>
/// <param name="outFile"></param>
private void CombineMultiplePDFs(List<string> files, string outFile)
{
int pageOffset = 0;
int f = 0;
iTextSharp.text.Document document = null;
PdfCopy writer = null;
foreach (string file in files)
{
// we create a reader for a certain document
PdfReader reader = new PdfReader(file);
reader.ConsolidateNamedDestinations();
// we retrieve the total number of pages
int n = reader.NumberOfPages;
pageOffset += n;
if (f == 0)
{
// step 1: creation of a document-object
document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
writer = new PdfCopy(document, new FileStream(outFile, FileMode.Create));
// step 3: we open the document
document.Open();
}
// step 4: we add content
for (int i = 0; i < n; )
{
++i;
if (writer != null)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
writer.AddPage(page);
}
}
PRAcroForm form = reader.AcroForm;
if (form != null && writer != null)
{
writer.CopyAcroForm(reader);
}
f++;
}
// step 5: we close the document
if (document != null)
{
document.Close();
}
}
The PDF File is then sitting on the server (e.g. "~/Invoices/0223.pdf") ready to attach to an email like so:
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(WebConfig.GetWebConfigKey(AppSettingsKey.ReplyEmailAddress.ToString()));
mailMessage.To.Add(new MailAddress(user.Email));
mailMessage.Subject = emailTemplate.TemplateSubject;
mailMessage.Body = emailTemplate.TemplateContent;
mailMessage.IsBodyHtml = false;
mailMessage.Attachments.Add(new Attachment(HttpContext.Current.Server.MapPath("/Invoices/" + invoiceId + ".pdf")));
SmtpClient client = new SmtpClient();
try
{
client.Send(mailMessage);
}
catch{...}{
//Error handling
}
client.Dispose();
Then I attempt to delete it:
File.Delete(HttpContext.Current.Server.MapPath("/Invoices/" + invoiceId + ".pdf"));