1

電子メールに添付して送信するC#MVCアプリケーションでPDF請求書を作成しています。理想的には、電子メールが送信されたら、請求書を削除してサーバースペースを解放し、プライバシー/セキュリティを向上させたいと考えています。私はそれを行うためのコードを書きましたが、ファイルが別のプロセスによってロックされているため、50%の確率で失敗します(ファイルをロックしているのが作成/書き込みプロセスなのか、電子メール送信なのかはわかりません)。メールを非同期で送信しています(つまり、削除するコードはメールが送信されるまで実行されません)。

この問題を処理する方法に関するヒントをいただければ幸いです。古いファイルをクリーンアップするジョブを実行することはできますが、移動しながらクリーンアップしたいと思います...

PDFを生成するためにiTextSharpを使用していることを忘れました-その核心は、このコードが最終的な請求書を生成するために使用されることです(ドラマなしでパラメーターとして渡されたファイルのリストを削除できます):

/// <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

4 に答える 4

6

ファイルをディスクに保存し、パフォーマンス、IO、および削除の問題が発生する代わりに、PDFおよびメールライブラリがPDFのMemoryStreamへの書き込み、およびそのストリームの電子メールへの添付をサポートしているかどうかを確認してください。

于 2012-05-17T12:25:38.887 に答える
3

FileStreamを使用してファイルを開いたり読み取ったりしていますか?

FileStreamから継承するストリームを使用して、ストリームが閉じたときにファイルを削除することができます。

/// <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);
    }
}
于 2012-05-17T11:56:49.813 に答える
0

私はあなたと同じ問題を抱えており、私がしたことは、PDFファイルを/ trashのような別のディレクトリに移動してから、このディレクトリのファイルを削除することでした。これは私にとって問題を解決します。

于 2012-05-17T11:55:47.613 に答える
-1

ファイルをアプリDBに保存できます。このようにして、別のプロセスの問題によってロックされることはありません。その後、それを削除することができます。また、行にタイムスタンプを付けることもできます。これにより、アプリが壊れた場合に、将来的に古いファイルを簡単に削除できるようになります。

于 2012-05-17T12:07:00.957 に答える