iTextSharp - Mengirim pdf dalam memori dalam lampiran email

100

Saya telah mengajukan beberapa pertanyaan di sini tetapi masih mengalami masalah. Saya akan menghargai jika Anda dapat memberi tahu saya kesalahan apa yang saya lakukan dalam kode saya. Saya menjalankan kode di atas dari halaman ASP.Net dan mendapatkan "Tidak Dapat Mengakses Arus Tertutup".

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("[email protected]", "[email protected]")
{
    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("[email protected]", "my_password")
};

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

Terima kasih!!!

EDIT:

Sekadar membantu seseorang mencari jawaban atas pertanyaan ini, kode untuk mengirim file pdf yang dilampirkan ke email tanpa harus membuat file secara fisik ada di bawah ini (terima kasih kepada Ichiban dan 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("[email protected]", "[email protected]")
{
    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("[email protected]", "password")

};

smtp.Send(mm);
Gus Cavalcanti
sumber
3
Terima kasih telah mengajukan pertanyaan ini, itulah yang saya cari.
Hardwareguy
1
terima kasih untuk barisnya position=0. selamatkan aku!
Yisroel M. Olewski
2
Persis yang saya butuhkan bekerja dengan sempurna, terima kasih banyak! Saya terjebak saat menutup dokumen tetapi tidak pada aliran: writer.CloseStream = false; membereskannya untukku.
Baxter
2
@Semil saat memberikan hadiah untuk pertanyaan lama dengan jawaban yang diterima, Anda benar-benar harus menunjukkan apa yang Anda lewatkan dalam jawaban.
mkl
writer.CloseStream = salah; menyelamatkan saya juga, kehilangan itu dalam metode yang menggunakan iTextSharp untuk mengubah HTML ke PDF. Sebelumnya, melewatkan aliran memori ke fungsi email saya gagal karena aliran ditutup. Terima kasih.
Alec Menconi

Jawaban:

81

Sudahkah Anda mencoba:

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

Jika ingatanku benar, ini memecahkan masalah serupa di proyek sebelumnya.

Lihat http://forums.asp.net/t/1093198.aspx

brianng.dll
sumber
1
Metode set_CloseStream hanya tersedia dalam versi Java. Ini adalah iTextSharp (.NET)
ichiban
Maaf, sekali lagi saya sudah lama tidak menggunakan iTextSharp (.NET), meskipun versi yang saya gunakan pasti memiliki set_CloseStream.
brianng
1
Berubah menjadi writer.CloseStream, dan menyertakan tautan terkait.
brianng
1
Brianng, saya sangat menghargai bantuan Anda. Aku sadar kau dan Ichiban seperti menahan tanganku untuk itu. Terima kasih!
Gus Cavalcanti
Jika kita menjaga penulis tetap hidup, kapankah kita seharusnya melakukannya writer.Flush()?
Blaise
18

Saya mencoba kode yang diposting oleh brianng dan berhasil. Ubah saja bagian atas kode menjadi ini:

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*/
ichiban
sumber
3
Terima kasih telah meluangkan waktu untuk memverifikasi!
brianng
1
Hai Ichiban, Ini mengkompilasi dan sebenarnya mengirimkan email dengan lampiran, tetapi dokumen pdf terlampir menemukan 0kb. Apakah Anda benar-benar membuka pdf yang dikirimi email?
Gus Cavalcanti
2
@Gustavo, file terbuka dengan benar di penampil Acrobat. Ini sekitar 900 Bytes. Pastikan Anda menjaga baris: memoryStream.Position = 0; tepat setelah doc.Close (). Saya lupa menyebutkan itu. (lihat pembaruan di atas)
ichiban
1
IYA! Terima kasih banyak teman-teman. Akhirnya berhasil. Karena jawaban Ichiban didasarkan pada jawaban brianng, saya rasa cukup adil untuk menandai jawaban brianng sebagai benar.
Gus Cavalcanti
3

Dapatkah Anda membersihkan dokumen atau aliran memori lalu menutupnya setelah Anda melampirkannya?

James Conigliaro
sumber
Hai James. Saya melakukan ini dan hasilnya tidak berubah - saya masih mendapatkan kesalahan "Tidak Dapat Mengakses Arus Tertutup". :( Ide lain?
Gus Cavalcanti
3

Mungkin memanggil doc.Close () Membuang aliran yang mendasarinya. Coba hapus doc.Close () dan sebagai ganti baris itu, setel memoryStream.Position = 0;

Atau Anda dapat menggunakan file temp:

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("[email protected]", "[email protected]")
    {
        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("[email protected]", "my_password")
    };

    smtp.Send(mm);
}
finally
{
    File.Delete(tempFilePath);
}
huseyint.dll
sumber
huseyint, saya melakukan apa yang Anda sarankan dan file pdf dikirim, tetapi panjangnya hanya 15 byte. Ketika saya mencoba membukanya, itu rusak. Saya merasa saya hampir sampai dengan saran Anda. Ada ide lain? Terima kasih!
Gus Cavalcanti
Kemudian coba memoryStream.Flush (); sebelum mengatur Posisi
huseyint
Hal yang sama. File yang dikirim hampir kosong dan rusak. :(
Gus Cavalcanti
Apakah Anda mencoba "Membuat file temporer"?
huseyint
Saya sedang mengerjakannya sekarang dan memberi tahu Anda segera. Terima kasih!
Gus Cavalcanti
1

Saya memiliki masalah yang sama dan saya menggunakan posting ini untuk mengatasinya. Dalam kode yang ditulis oleh 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"));

Saya pikir daripada menulis

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

Buat saja Arus baru

MemoryStream m = new MemoryStream(memoryStream);

dan kemudian menelepon

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

Keduanya berfungsi, tetapi menurut saya lebih baik membuat aliran baru

Zein Sleiman
sumber
Mengapa lebih baik membuat aliran baru?
Andy
Ini bukan. Ini hanya membuang-buang memori dan waktu CPU karena byte harus disalin dari satu ke yang lain.
Serguei Fedorov
Tidak ingat mengapa saya mengatakan itu lebih baik. Saya pikir saya mungkin bermaksud membuatnya lebih jelas. Maaf baru saja melihat ini. Sudah lama :)
Zein Sleiman