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-файл, прикріплений до електронної пошти, не потребуючи фізичного створення файлу, знаходиться нижче (завдяки Ічібану та Брайангу):

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
Саме те, що мені потрібно, відмінно дякую тобі! Я застряг при закритті документа, але не потоку: Writ.CloseStream = false; очистив це для мене.
Бакстер

2
@Semil, коли ви ставите щедро за старе запитання з прийнятою відповіддю, ви дійсно повинні якось вказати, що ви пропускаєте у відповіді.
mkl

Writer.CloseStream = хибний; врятував мене також, не вистачало цього в методі, який використовує iTextSharp для перетворення HTML у PDF. Раніше передача потоку пам'яті моїй пошті не вдалося через закритий потік. Дякую.
Алек Менконі

Відповіді:


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
Брайанго, я дуже ціную вашу допомогу. Я усвідомлюю, що ти і Ічібан наче провели мою руку. Дякую!
Gus Cavalcanti

Якщо ми будемо тримати письменника в живих, коли ми гадаємо, що writer.Flush()тоді?
Блез

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
Привіт Ічібан, він компілюється, і він фактично надсилає електронний лист із вкладенням, але доданий PDF-документ натрапляє на 0 кб. Ви справді відкрили pdf, надісланий електронним листом?
Gus Cavalcanti

2
@Gustavo, файл переглядається правильно у переглядачі Acrobat. Це близько 900 байт. Переконайтеся, що ви тримаєте рядок: memoryStream.Position = 0; відразу після doc.Закрити (). Я забув це згадати. (див. оновлення вище)
ichiban

1
ТАК! Дуже дякую, хлопці. Це нарешті спрацювало. Оскільки відповідь Ічібана базувалася на відповіді Брайанга, я вважаю, що відповідь Бріанга справедливо позначати правильною.
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);
}

huseyint, я зробив те, що ви запропонували, і файл PDF буде надісланий, але він становить лише 15 байт. Коли я намагаюся його відкрити, він зіпсований. Я відчуваю, що я майже з вашою пропозицією. Будь-які інші ідеї? Дякую!
Gus Cavalcanti

Потім спробуйте memoryStream.Flush (); перед встановленням Позиції
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"));

Обидва працюють, але я думаю, що краще створити новий потік


Чому краще створити новий потік?
Енді

Це не. Це марна пам'ять і час процесора, тому що байти повинні бути скопійовані з одного в інший.
Сергей Федоров

Не пам'ятаю, чому я сказав, що це краще. Я думаю, я міг би означати, що це зрозуміліше. Вибачте щойно це побачив. Був давно :)
Zein Sleiman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.