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

2
สิ่งที่ฉันต้องการทำงานได้อย่างสมบูรณ์ขอบคุณมาก! ฉันติดขัดในการปิดเอกสาร แต่ไม่ใช่สตรีม: writer.CloseStream = false; เคลียร์มันให้ฉัน
Baxter

2
@ เซมิลเมื่อให้ความสำคัญกับคำถามเก่า ๆ พร้อมคำตอบที่ยอมรับคุณควรระบุสิ่งที่คุณพลาดในคำตอบ
mkl

writer.CloseStream = false; ช่วยฉันด้วยเช่นกันหายไปในวิธีการที่ใช้ iTextSharp เพื่อเปลี่ยน HTML เป็น PDF ก่อนหน้านี้การส่งสตรีมหน่วยความจำไปยังฟังก์ชันเมลของฉันล้มเหลวเนื่องจากสตรีมถูกปิด ขอบคุณ.
Alec Menconi

คำตอบ:


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)
ichiban

ขออภัยอีกครั้งฉันไม่ได้ใช้ iTextSharp (.NET) มาระยะหนึ่งแล้วแม้ว่าเวอร์ชันที่ฉันใช้จะมี set_CloseStream ก็ตาม
brianng

1
เปลี่ยนเป็น writer.CloseStream และรวมลิงค์ที่เกี่ยวข้อง
brianng

1
Brianng ฉันขอขอบคุณสำหรับความช่วยเหลือของคุณ ฉันรู้ว่าคุณและอิจิบังจับมือฉันผ่านมัน ขอบคุณ!
Gus Cavalcanti

ถ้าเราให้นักเขียนยังมีชีวิตอยู่เราจะคิดว่าเมื่อไหร่writer.Flush()?
Blaise

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

1
สวัสดี Ichiban มันรวบรวมและส่งอีเมลพร้อมไฟล์แนบจริง ๆ แต่เอกสาร pdf ที่แนบมามี 0kb คุณเปิดไฟล์ PDF ที่ส่งอีเมลไปจริงหรือไม่?
Gus Cavalcanti

2
@Gustavo ไฟล์จะเปิดขึ้นอย่างถูกต้องในโปรแกรมดู Acrobat มีขนาดประมาณ 900 ไบต์ ตรวจสอบให้แน่ใจว่าคุณเก็บบรรทัด: memoryStream.Position = 0; หลัง doc.Close () ฉันลืมที่จะพูดถึงเรื่องนั้น (ดูอัปเดตด้านบน)
ichiban

1
ใช่! ขอบคุณพวกคุณมาก ๆ ในที่สุดมันก็ได้ผล เนื่องจากคำตอบของ Ichiban เป็นไปตามของ brianng ฉันคิดว่ามันยุติธรรมที่จะทำเครื่องหมายว่าคำตอบของ brianng ถูกต้อง
Gus Cavalcanti

3

คุณสามารถล้างเอกสารหรือสตรีมหน่วยความจำแล้วปิดหลังจากแนบได้หรือไม่?


สวัสดีเจมส์ ฉันทำสิ่งนี้แล้ว แต่ผลลัพธ์ก็ไม่เปลี่ยนแปลง - ฉันยังคงได้รับข้อผิดพลาด "ไม่สามารถเข้าถึงสตรีมแบบปิด" :( ความคิดอื่น ๆ ?
Gus Cavalcanti

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

คำใบ้ฉันทำตามที่คุณแนะนำและส่งไฟล์ pdf แล้ว แต่มีความยาวเพียง 15 ไบต์ เมื่อฉันลองเปิดมันเสียหาย ฉันรู้สึกว่าเกือบจะพร้อมรับคำแนะนำของคุณแล้ว ความคิดอื่น ๆ ? ขอบคุณ!
Gus Cavalcanti

จากนั้นลอง memoryStream.Flush (); ก่อนกำหนด Position
huseyint

สิ่งเดียวกัน. ไฟล์ถูกส่งเกือบว่างเปล่าและเสียหาย :(
Gus Cavalcanti

คุณได้ลอง "สร้างไฟล์ชั่วคราว" หรือไม่
huseyint

ฉันกำลังดำเนินการแก้ไขและจะแจ้งให้คุณทราบในไม่ช้า ขอบคุณ!
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"));

ทำงานทั้งคู่ แต่คิดว่าสร้างกระแสใหม่ดีกว่า


ทำไมสร้างกระแสใหม่ดีกว่า
Andy

มันไม่ใช่. เสียเวลาหน่วยความจำและ CPU เพราะต้องคัดลอกไบต์จากที่หนึ่งไปยังอีกที่หนึ่ง
Serguei Fedorov

จำไม่ได้ว่าทำไมฉันถึงบอกว่ามันดีกว่า ฉันคิดว่าฉันอาจหมายความว่ามันชัดเจนกว่านี้ ขออภัยเพิ่งเห็นสิ่งนี้ เป็นเวลานานแล้ว :)
Zein Sleiman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.