iTextSharp - Bir e-posta ekinde bellek içi pdf gönderme


100

Burada birkaç soru sordum ama hala sorun yaşıyorum. Kodumda neyi yanlış yaptığımı söylerseniz sevinirim. Yukarıdaki kodu bir ASP.Net sayfasından çalıştırıyorum ve "Kapalı Bir Akışa Erişilemiyor" mesajı alıyorum.

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

Teşekkürler!!!

DÜZENLE:

Sadece bu sorunun cevabını arayan birine yardımcı olmak için, dosyayı fiziksel olarak oluşturmak zorunda kalmadan bir e-postaya eklenmiş bir pdf dosyasını gönderme kodu aşağıdadır (Ichiban ve Brianng sayesinde):

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
Bu soruyu sorduğunuz için teşekkürler, tam olarak aradığım şey buydu.
Hardwareguy

1
hattı için teşekkürler position=0. beni kurtardı!
Yisroel M. Olewski

2
Tam olarak ihtiyacım olan şey mükemmel çalışıyor, çok teşekkür ederim! Belgeyi kapatırken takılı kaldım ama akışı değil: writer.CloseStream = false; benim için temizledi.
Baxter

2
@Semil, eski bir soruya kabul edilmiş bir cevabı olan bir ödül koyarken, cevapta neyi kaçırdığınızı gerçekten belirtmelisiniz.
mkl

writer.CloseStream = yanlış; beni de kurtardı, HTML'yi PDF'ye dönüştürmek için iTextSharp kullanan bir yöntemde eksikti. Daha önce, memorystream'i posta işlevime geçirme, akışın kapatılması nedeniyle başarısız oldu. Teşekkürler.
Alec Menconi

Yanıtlar:


81

Denedin mi:

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

Hafızam bana doğru hizmet ediyorsa, bu önceki bir projede benzer bir sorunu çözdü.

Bkz. Http://forums.asp.net/t/1093198.aspx


1
Set_CloseStream yöntemi yalnızca Java sürümünde mevcuttur. Bu iTextSharp (.NET)
ichiban

Üzgünüm, yine bir süredir iTextSharp (.NET) kullanmadım, ancak kullandığım sürümde kesinlikle set_CloseStream vardı.
brianng

1
Writer.CloseStream olarak değiştirildi ve ilgili bağlantı eklendi.
brianng

1
Brianng, yardımın için gerçekten minnettarım. Senin ve Ichiban'ın bir şekilde elimi tuttuğunun farkındayım. Teşekkürler!
Gus Cavalcanti

Yazarı hayatta tutarsak, ne zaman yaşamalıyız writer.Flush()?
Blaise

18

Brianng tarafından gönderilen kodu denedim ve işe yaradı. Kodun üst kısmını şuna değiştirin:

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
Doğrulamaya zaman ayırdığınız için teşekkür ederiz!
brianng

1
Merhaba Ichiban, derliyor ve aslında ekli e-postayı gönderiyor, ancak ekli pdf belgesi 0kb ile karşımıza çıkıyor. Bir e-postanın gönderdiği pdf dosyasını gerçekten açtınız mı?
Gus Cavalcanti

2
@Gustavo, dosya Acrobat görüntüleyicide doğru bir şekilde açılıyor. Yaklaşık 900 Bayttır. Şu satırı koruduğunuzdan emin olun: memoryStream.Position = 0; doc.Close () 'dan hemen sonra. Bundan bahsetmeyi unuttum. (yukarıdaki güncellemeye bakın)
ichiban

1
EVET! Çok teşekkür ederim beyler. Sonunda işe yaradı. Ichiban'ın cevabı brianng'a dayandığından, brianng'ın cevabını doğru olarak işaretlemenin adil olduğunu düşünüyorum.
Gus Cavalcanti

3

Eğer Can temizlemek belgeyi veya bellek akışı ve bunu takmak sonra sonra kapatın?


Merhaba James. Bunu yaptım ve sonuç değişmedi - hala "Kapalı Bir Akıma Erişilemiyor" hatası alıyorum. :( Başka fikirler?
Gus Cavalcanti

3

Muhtemelen doc.Close () 'yi çağırmak, temeldeki akışı ortadan kaldırır. Doc.Close () 'yi kaldırmayı deneyin ve bu satır yerine memoryStream.Position = 0 ayarlayın;

Alternatif olarak bir geçici dosya da kullanabilirsiniz:

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, önerdiğin şeyi yaptım ve pdf dosyası gönderildi, ancak sadece 15 bayt uzunluğunda. Açmayı denediğimde bozuk. Senin önerinle neredeyse orada olduğumu hissediyorum. Başka fikrin var mı? Teşekkürler!
Gus Cavalcanti

Sonra memoryStream.Flush (); Pozisyonu Belirlemeden Önce
huseyint

Aynı şey. Dosya neredeyse boş ve bozuk olarak gönderilir. :(
Gus Cavalcanti

"Geçici dosya oluşturma" yı denediniz mi?
huseyint

Şu anda bunun üzerinde çalışıyorum ve kısa süre içinde size haber vereceğim. Teşekkürler!
Gus Cavalcanti

1

Ben de aynı sorunu yaşadım ve çözmek için bu yazıyı kullandım. Brianng tarafından yazılan kodda

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

Yazmak yerine düşünüyorum

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

Sadece yeni bir Akış oluşturun

MemoryStream m = new MemoryStream(memoryStream);

ve sonra ara

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

İkisi de işe yarıyor ama bence yeni akışı oluşturmak daha iyi


Yeni bir akış oluşturmak neden daha iyidir?
Andy

Değil. Bu bir bellek ve CPU zamanı israfıdır çünkü baytların birinden diğerine kopyalanması gerekir.
Serguei Fedorov

Neden daha iyi dediğimi hatırlamayın. Sanırım daha açık olduğunu kastetmiştim. Üzgünüm az önce bunu gördüm. Uzun zaman oldu :)
Zein Sleiman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.