关闭后立即从Web服务器删除文件的C#技术

时间:2012-05-17 11:50:40

标签: c# asp.net-mvc itextsharp delete-file

我正在C#MVC应用程序中创建PDF发票,我附加到电子邮件并发送,理想情况下,一旦发送电子邮件,我想删除发票以释放服务器空间并提高隐私/安全性。我已编写代码来执行此操作,但它在50%的时间内失败,因为该文件被另一个进程锁定(我不确定是创建/写入进程是锁定它还是电子邮件发送)。我正在异步发送电子邮件(即删除的代码在电子邮件发送之前不会执行)。

我很欣赏有关如何处理此问题的一些提示。我可以找一份工作来清理旧文件,但我更喜欢在我去的时候把它们清理干净......

我忘了提到我正在使用iTextSharp来生成PDF - 它的关键是这个代码用于生成最终发票(我能够删除作为参数传入的文件列表而没有戏剧性):< / p>

/// <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();
            }
        }

然后PDF文件就位于服务器上(例如“〜/ Invoices / 0223.pdf”),准备附加到这样的电子邮件:

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();

然后我尝试删除它:

File.Delete(HttpContext.Current.Server.MapPath("/Invoices/" + invoiceId + ".pdf"));

4 个答案:

答案 0 :(得分:6)

不是将文件保存到磁盘,还会导致性能,IO和删除问题,而是查看您的PDF和邮件库是否支持将PDF写入MemoryStream,并将该流附加到电子邮件中。

答案 1 :(得分:3)

您使用FileStream打开/读取文件吗?

您可以尝试使用从FileStream继承的Stream,并在关闭流时删除该文件:

/// <summary>
/// FileStream that automatically delete the file when closing
/// </summary>
public class AutoDeleteFileStream : FileStream
{
    private string _fileName;

    public AutoDeleteFileStream(string fileName, FileMode fileMode, FileAccess fileAccess)
        : base(fileName, fileMode, fileAccess)
    {
        this._fileName = fileName;
    }

    public AutoDeleteFileStream(string fileName, FileMode fileMode)
        : base(fileName, fileMode)
    {
        this._fileName = fileName;
    }

    public override void Close()
    {
        base.Close();
        if (!string.IsNullOrEmpty(_fileName))
            File.Delete(_fileName);
    }
}

答案 2 :(得分:0)

我和你有同样的问题,我所做的是将PDF文件移动到/ trash这样的另一个目录,然后删除该目录的文件。这解决了我的问题。

答案 3 :(得分:-1)

您可以将文件保存在应用数据库中。这样,您就不会受到另一个进程问题的锁定。然后你可以删除它。此外,您可以在行上添加时间戳,这样,如果您的应用程序中断,将来删除旧文件会更容易。