2

Requirment: To generate invoice in pdf format on company template and send it in email.

Approach I used:

  1. Placed the company template at path: ~Content/InvoiceTemplate/
  2. Using iTextsharp Pdf stamper, generated pdf, saved it at path: ~/Content/reports/
  3. In email module, picked the file generated above and attached to email to be sent

Problem: Every invoice generated is being stored on application server, making application heavier day by day.

Question: What is the other way out to send the generated in voice in email, without saving it on application server?

Code:

    public static void WriteInTemplate(List<Models.Statement> statementList)
    {
        try
        {
            string invoiceNumber = statementList.FirstOrDefault().Invoice.ToString().Trim();

            using (Document document = new Document())
            {
                FileStream fileStream = new FileStream(HostingEnvironment.MapPath("~/Content/reports/" + invoiceNumber + ".pdf"), FileMode.Create);
                using (PdfSmartCopy smartCopy = new PdfSmartCopy(document, fileStream))
                {
                    document.Open();

                    int statementCounter = 0;
                    int numberOfItems = statementList.Count();
                    int remainingItems = numberOfItems;
                    int maxItemsPerPage = 17;
                    if (remainingItems > 0)
                    {
                        do
                        {
                            if (remainingItems < maxItemsPerPage)
                                maxItemsPerPage = remainingItems;


                            PdfReader pdfReader = new PdfReader(HostingEnvironment.MapPath("~/Content/InvoiceTemplate/invoiceTemplate.pdf"));
                            using (var memoryStream = new MemoryStream())
                            {
                                using (PdfStamper pdfStamper = new PdfStamper(pdfReader, memoryStream))
                                {
                                    string month = null;
                                    string day = null;
                                    string year = null;

                                    AcroFields pdfFields = pdfStamper.AcroFields;
                                    {//billing address
                                        pdfFields.SetField("BillToCompany", statementList.FirstOrDefault().BillToCompany.ToString().Trim().ToUpper());
                                        pdfFields.SetField("BillToContact", statementList.FirstOrDefault().BillToContact.ToString().Trim().ToUpper());
                                   }
           //---------------------snip------------------------------//
           //---------------------snip------------------------------//

                                    }
                                    {//invoice sum up
                                        double subTotal = Convert.ToDouble(statementList.FirstOrDefault().Subtotal);
                                        pdfFields.SetField("Subtotal", statementList.FirstOrDefault().Subtotal.ToString("0.00").Trim());

                                        double misc = Convert.ToDouble(statementList.FirstOrDefault().Misc);
                                        pdfFields.SetField("Misc", statementList.FirstOrDefault().Misc.ToString("0.00").Trim());

                                        double tax = Convert.ToDouble(statementList.FirstOrDefault().Tax);
                                        pdfFields.SetField("Tax", statementList.FirstOrDefault().Tax.ToString("0.00").Trim());

                                    }
                                    pdfStamper.FormFlattening = true; // generate a flat PDF 

                                }
                                pdfReader = new PdfReader(memoryStream.ToArray());
                                smartCopy.AddPage(smartCopy.GetImportedPage(pdfReader, 1));

                            }
                            remainingItems = remainingItems - maxItemsPerPage;

                        } while (remainingItems > 0);
                    }
                }
            }

            emailController.CreateMessageWithAttachment(invoiceNumber);
        }
        catch (Exception e)
        {
        }

    }
14578446
  • 1,044
  • 7
  • 30
  • 50

3 Answers3

2

You can try to attach the file from a memory stream. You can search Google for "C# Attach file from memory stream".

Here is a sample snippet:

 mail.Attachments.Add(new Attachment(memoryStream, "example.txt", "text/plain"));

Or:

email attachment from the MemoryStream comes empty

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/049420de-7e93-4fcb-9920-0c1cdf4ca420/

http://www.codeproject.com/KB/IP/InMemoryMailAttachment.aspx

Community
  • 1
  • 1
Nick Bork
  • 4,831
  • 1
  • 24
  • 25
2

If the pdf files aren't too large, and you're not using a server farm, and you don't have millions of people generating invoices at the same time..

Then you could always use a MemoryStream and pass the memory stream to your email service.

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
0

Instead of creating a file in your application directory you should try creating files in temp folder.. and when you are done with the file you should delete them.. this way files won't take so much space on your drive..

this is a tempfile class that i have used with iTextSharp to export pdf after filling the form.

  sealed class TempFile : IDisposable
    {
        string path;
        public TempFile() : this(System.IO.Path.GetTempFileName()) { }

        public TempFile(string path)
        {
            if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
            this.path = path;
        }
        public string Path
        {
            get
            {
                if (path == null) throw new ObjectDisposedException(GetType().Name);
                return path;
            }
        }
        ~TempFile() { Dispose(false); }
        public void Dispose() { Dispose(true); }
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
            if (path != null)
            {
                try { File.Delete(path); }
                catch { } // best effort
                path = null;
            }
        }
    }

you should try

using(TempFile file = new TempFile())
{
.....= new FileStream(file.Path,.....)
//pdf form filling using iTextSharp

var arry = GetBytesArray(file.Path);
//Send Array to response and set content type to pdf..

}
Shoaib Shaikh
  • 4,565
  • 1
  • 27
  • 35
  • Yikes. Shoaib - this code doesn't follow the dispose pattern properly. You reference 'path' in the case of the finalizer being called which is a crash waiting to happen as path may be invalid at that point. See here: http://www.atalasoft.com/cs/blogs/stevehawley/archive/2006/09/21/10887.aspx – plinth Jan 19 '12 at 18:41
  • i didn't get. the artile is more about separating disposing of managed and unmanaged resources.. what do you mean by path may be invalid? – Shoaib Shaikh Jan 19 '12 at 18:52
  • 2
    When Dispose(bool disposing) is called with disposing == false, any managed type in your class may already be invalid, including the string path. NEVER reference any garbage collected type when disposing == false. If you don't understand this, just follow the pattern in the blog and you can't go wrong. – plinth Jan 19 '12 at 19:32