我一直致力于一个项目,要求我通过Mandrill电子邮件附上一份PDF文件(一份载有动态数据的传真封面),我有最糟糕的时间来分析各种不同的方法来实现这个看似简单的任务。以下是我的项目的具体内容:
现在我需要:
那么实现这一目标的最有效和最轻的方法是什么?
答案 0 :(得分:1)
我编制并测试了我新创建的项目,以下工作非常顺利(我毫不犹豫地说完美'或者完美'因为我相信有人会找到更好的完成我所做的事的方式。正如您将要看到的那样,我将数据保存到图像中并将这些图像放到新创建的PDF页面上。
父方法
public static void SendEmail()
{
try
{
/*
Standard code to prepare Mandrill email.
'EmailMessageObj' is the Mandrill.EmailMessage object
*/
//Create PDF with data
Pdf pdfObject = new Pdf();
PdfDocument document = Pdf.Document(param1, param2, pdfObject); //create PDF document and pass in object's data. Sets pdfObj properties, such as the byte[] PdfBytes seen below
using (MemoryStream stream = new MemoryStream())
{
// Create email attachment
EmailMessageObj.attachments = new[]
{
new attachment
{
content = Convert.ToBase64String(pdfObject.PdfBytes),
name = "Fax Cover Sheet.pdf",
type = "application/pdf"
}
};
}
api.SendMessage(EmailMessageObj);
}
catch (Exception error)
{
Console.WriteLine("Could not send email." + error);
}
}
Pdf对象
我添加了对以下内容的引用:' HtmlRenderer',' HtmlRenderer.WinForms',' PdfSharp'
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using TheArtOfDev.HtmlRenderer.WinForms;
class Pdf
{
public string PdfFileDirectory { get; set; }
public string PdfCoverFileName { get; set; }
public string LogoFileName { get; set; }
public Image PageOne { get; set; }
public Image PageTwo { get; set; }
public byte[] PdfBytes { get; set; }
public Pdf()
{
PdfFileDirectory = Settings.BaseBaseDirectory + @"\";
PdfCoverFileName = "FaxCoverPage.pdf";
LogoFileName = "Logo.jpg";
PageOne = null;
PageTwo = null;
PdfBytes = null;
}
/// <summary>
/// The PDFsharp PDF Document. This creates images out of the data and then puts those images onto the (created within) PDF pages.
/// </summary>
/// <param name="addressedTo">The person this is being sent/addressed to</param>
/// <param name="dataFormattedIntoTable">The formatted data table</param>
/// <param name="pdfObj">The Pdf object</param>
/// <returns></returns>
public static PdfDocument Document(string addressedTo, string dataFormattedIntoTable, Pdf pdfObj)
{
//See https://htmlrenderer.codeplex.com/wikipage?title=Image%20generation for documentation
//First Page (To, From, disclaimer, etc.)
pdfObj.PageOne = HtmlRender.RenderToImageGdiPlus(CoverPage_Front(addressedTo), new Size(600, 0), new Size(800, 0)); //Create an image from passed-in data. Set Min/Max size restriction
using (MemoryStream stream = new MemoryStream())
{
pdfObj.PageOne.Save(stream, ImageFormat.Png); //save via stream so I do not have to save this file locally and can then dispose of it, thus freeing things up
}
//Second Page (logo and data table)
pdfObj.PageTwo = HtmlRender.RenderToImageGdiPlus(CoverPage_Content(addressedTo, dataFormattedIntoTable), new Size(600, 0), new Size(800, 0)); //Create an image from passed-in data. Set Min/Max size restriction
using (MemoryStream stream = new MemoryStream())
{
pdfObj.PageTwo.Save(stream, ImageFormat.Png); //save via stream so I do not have to save this file locally and can then dispose of it, thus freeing things up
}
// Create a new PDF document
PdfDocument document = new PdfDocument();
// Create an empty page
PdfPage page = document.AddPage();
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
//I only want two pages so..
for (int pageCounter = 0; pageCounter < 2; pageCounter++)
{
if (pageCounter == 0)
{
// draw Fax cover page (To, From, disclaimer, etc.)
gfx.DrawImage(pdfObj.PageOne, 0f, 35f); //fax cover page image, margin-left, margin-top
// since this is the first page, add a second one. This will NOT be done on subsequent pages because we are planning on only have 2 pages for now
page = document.AddPage(); //add the second page
gfx = XGraphics.FromPdfPage(page);
}
else
{
// draw logo
Image LogoFileName = Image.FromFile(pdfObj.PdfFileDirectory + pdfObj.LogoFileName); //I store the logo locally
gfx.DrawImage(LogoFileName, 130f, 35f); //logo image, margin-left, margin-top
// draw Table with passed-in data
gfx.DrawImage(pdfObj.PageTwo, 0f, 100f); //the main content. The margin-top is set to 100f so it sits below the logo.
}
}
using (MemoryStream stream = new MemoryStream())
{
document.Save(stream, true); //save via stream so I do not have to save this file locally and can then dispose of it, thus freeing things up
pdfObj.PdfBytes = stream.ToArray(); //save the byte array of the stream to the object's byte[] property. Mandrill attachments need to be byte arrays and THIS is what we will be attaching
}
return document;
}
/// <summary>
/// The Fax Cover Page is two pages - this is the first one. It displays the From, To, and disclaimer
/// </summary>
/// <param name="addressedTo">The name of the person this is being sent to.</param>
/// <returns></returns>
public static string CoverPage_Front(string addressedTo)
{
// Obviously altered.. You may format your fax cover sheet however you like
return @"<html>
<body>
<div>
To: " + addressedTo + @", Cappuccino catcher luxurious admiral charity donate, luxurious big daft brush mouth coiffure clive dunn dickie davies charity donate admiral give him what-for john cleese. By jingo. big daft brush joseph stalin charming villain.
</div>
</body>
</html>";
}
/// <summary>
/// The Fax Cover Page is two pages - this is the second one. It displays the logo and the table of data
/// </summary>
/// <param name="addressedTo"></param>
/// <param name="dataFormattedIntoTable"></param>
/// <returns></returns>
public static string CoverPage_Content(string addressedTo, string dataFormattedIntoTable)
{
// Obviously altered..
return @"<html>
<body>
<div>
<table border='0' cellpadding='0' style='background: #E8EBEB;'>
<tbody>
<tr>
<td style='padding: .75pt .75pt .75pt .75pt'>
<table border='0' cellpadding='0' style='background: white;'>
<tbody>
<tr>
<td style='border: none; border-bottom: solid #004A8F 4.5pt; padding: 0in 7.5pt 0in 7.5pt'>
To: " + addressedTo + @", Facial accessory doctor watson. wario arcu, yeoman farmer wario blue oyster bar charlie chaplin old man in pub hungarian nefarious cesar romero facial accessory doctor watson. arcu glorious facial hair? Frontiersman en time-warped cabbie great dictator um yesbaby toothbrush clone zone shopper.
" + dataFormattedIntoTable + @"
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>";
}
}
我真的希望这对你有所帮助!!这花了我一些时间来弄清楚它现在运作得很好。如果对此有任何改进,请告诉我,我将更新我的代码(和这篇文章)!