iTextSharp-電子メールの添付ファイルでインメモリpdfを送信する


100

ここでいくつか質問しましたが、まだ問題が解決していません。私のコードで私が間違っていることを教えていただければ幸いです。上記のコードをASP.Netページから実行すると、「閉じたストリームにアクセスできません」というメッセージが表示されます。

var doc = new Document();

MemoryStream memoryStream = new MemoryStream();

PdfWriter.GetInstance(doc, memoryStream);
doc.Open();
doc.Add(new Paragraph("First Paragraph"));
doc.Add(new Paragraph("Second Paragraph"));

doc.Close(); //if I remove this line the email attachment is sent but with 0 bytes 

MailMessage mm = new MailMessage("username@gmail.com", "username@gmail.com")
{
    Subject = "subject",
    IsBodyHtml = true,
    Body = "body"
};

mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));
SmtpClient smtp = new SmtpClient
{
    Host = "smtp.gmail.com",
    Port = 587,
    EnableSsl = true,
    Credentials = new NetworkCredential("username@gmail.com", "my_password")
};

smtp.Send(mm); //the "Cannot Access a Closed Stream" error is thrown here

ありがとう!!!

編集:

この質問の答えを探している人を助けるために、ファイルを物理的に作成せずに電子メールに添付されたpdfファイルを送信するコードを以下に示します(IchibanとBrianngに感謝)。

var doc = new Document();
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

doc.Open();
doc.Add(new Paragraph("First Paragraph"));
doc.Add(new Paragraph("Second Paragraph"));

writer.CloseStream = false;
doc.Close();
memoryStream.Position = 0;

MailMessage mm = new MailMessage("username@gmail.com", "username@gmail.com")
{
    Subject = "subject",
    IsBodyHtml = true,
    Body = "body"
};

mm.Attachments.Add(new Attachment(memoryStream, "filename.pdf"));
SmtpClient smtp = new SmtpClient
{
    Host = "smtp.gmail.com",
    Port = 587,
    EnableSsl = true,
    Credentials = new NetworkCredential("username@gmail.com", "password")

};

smtp.Send(mm);

3
この質問をしてくれてありがとう、それはまさに私が探していたものです。
Hardwareguy

1
の行をありがとうposition=0。助かりました!
Yisroel M. Olewski 2012年

2
まさに私が必要としているものは完璧に機能します。ストリームではなく、ドキュメントを閉じるのに行き詰まりました:writer.CloseStream = false; 私のためにそれを片付けました。
バクスター2014年

2
@Semil受け入れられた回答のある古い質問に賞金を出すとき、あなたは本当にどういうわけか答えであなたが逃したものを示すべきです。
mkl 2015

writer.CloseStream = false; 私も救いました、iTextSharpを使用してHTMLをPDFに変換するメソッドにはそれがありませんでした。以前は、メモリストリームをメール関数に渡すことが、ストリームが閉じられていたために失敗しました。ありがとう。
Alec Menconi、2015年

回答:


81

やってみました:

PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

// Build pdf code...

writer.CloseStream = false;
doc.Close();

// Build email

memoryStream.Position = 0;
mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));

私の記憶が正しく機能している場合、これは以前のプロジェクトの同様の問題を解決しました。

http://forums.asp.net/t/1093198.aspxを参照してください


1
set_CloseStreamメソッドは、Javaバージョンでのみ使用できます。これは、iTextSharp(.NET)
一番

申し訳ありませんが、私はしばらくの間iTextSharp(.NET)を使用していませんが、使用したバージョンには間違いなくset_CloseStreamがありました。
brianng 2009

1
writer.CloseStreamに変更され、関連リンクが含まれました。
brianng 2009

1
ブライアン、あなたの助けに本当に感謝しています。私はあなたと一番が私の手を握っていたことに気づきました。ありがとう!
Gus Cavalcanti

筆者が生きているとしたら、いつwriter.Flush()それを行うと思いますか?
Blaise 2014

18

私はbrianngが投稿したコードを試してみましたが、うまくいきました。コードの先頭をこれに変更するだけです:

var doc = new Document();
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream); //capture the object
doc.Open();
doc.Add(new Paragraph("First Paragraph"));
doc.Add(new Paragraph("Second Paragraph"));
writer.CloseStream = false; //set the closestream property
doc.close(); //close the document without closing the underlying stream
memoryStream.Position = 0;

/* remainder of your code stays the same*/

3
確認していただきありがとうございます。
brianng 2009

1
こんにちは、それはコンパイルされ、実際に添付ファイル付きの電子メールを送信しますが、添付されたpdfドキュメントは0kbで送信されます。電子メールで送信されたPDFを実際に開きましたか?
ガスカヴァルカンティ

2
@Gustavo、ファイルはAcrobatビューアで正しく開きます。約900バイトです。次の行を必ず使用してください。memoryStream.Position= 0; doc.Close()の直後。そのことを忘れていました。(上記の更新を参照)
ichiban

1
はい!本当にありがとうございました。ようやく機能しました。一番の答えはbrianngの答えに基づいていたので、brianngの答えを正しいとマークするのは公平だと思います。
Gus Cavalcanti、

3

ドキュメントまたはメモリストリームをフラッシュし、アタッチした後に閉じることはできますか?


こんにちはジェームズ。これを行っても結果は変わりませんでした-「閉じたストリームにアクセスできません」というエラーが表示されます。:(他のアイデア?
ガス・カヴァルカンティ

3

おそらくdoc.Close()を呼び出して、基になるストリームを破棄します。doc.Close()を削除してみて、その行の代わりにmemoryStream.Position = 0を設定してください。

または、一時ファイルを使用することもできます。

var tempFilePath = Path.GetTempFileName();

try 
{           
    var doc = new Document();

    PdfWriter.GetInstance(doc, File.OpenWrite(tempFilePath));
    doc.Open();
    doc.Add(new Paragraph("First Paragraph"));
    doc.Add(new Paragraph("Second Paragraph"));

    doc.Close();

    MailMessage mm = new MailMessage("username@gmail.com", "username@gmail.com")
    {
        Subject = "subject",
        IsBodyHtml = true,
        Body = "body"
    };

    mm.Attachments.Add(new Attachment(tempFilePath, "test.pdf"));
    SmtpClient smtp = new SmtpClient
    {
        Host = "smtp.gmail.com",
        Port = 587,
        EnableSsl = true,
        Credentials = new NetworkCredential("username@gmail.com", "my_password")
    };

    smtp.Send(mm);
}
finally
{
    File.Delete(tempFilePath);
}

huseyint、私はあなたが提案したことを行い、pdfファイルが送信されますが、それは15バイトの長さしかありません。開こうとすると破損しています。私はあなたの提案でほとんどそこにいるように感じます。他のアイデアはありますか?ありがとう!
ガスカヴァルカンティ

次に、memoryStream.Flush();を試してください。位置を設定する前
huseyint 2009

同じこと。ファイルはほとんど空で破損して送信されます。:(
ガス・カヴァルカンティ

「一時ファイルの作成」を試しましたか?
huseyint 2009

私は現在それを取り組んでおり、間もなくお知らせします。ありがとう!
Gus Cavalcanti、

1

同じ問題があり、この投稿を使用して解決しました.brianngによって書かれたコードでは

PdfWriter writer = PdfWriter.GetInstance(doc, memoryStream);

// Build pdf code...

writer.CloseStream = false;
doc.Close();

// Build email

memoryStream.Position = 0;
mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));

書く代わりに

writer.CloseStream = false and memoryStream.Position = 0;

新しいストリームを作成するだけです

MemoryStream m = new MemoryStream(memoryStream);

そして次に電話する

mm.Attachments.Add(new Attachment(memoryStream, "test.pdf"));

どちらも機能しますが、新しいストリームを作成する方が良いと思います


新しいストリームを作成する方が良いのはなぜですか?
アンディ

そうではありません。バイトを一方から他方へコピーする必要があるため、メモリとCPU時間の浪費です。
セルゲイフェドロフ2015年

私がそれがより良いと言った理由を覚えてはいけません。私はそれがより明確であることを意味したと思うかもしれません。見ただけで申し訳ありません。久しぶり:)
Zein Sleiman '10
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.