从html生成pdf并将其附加到电子邮件

时间:2017-05-31 09:34:28

标签: c# asp.net-mvc api abcpdf mailmessage

我遇到了一些可以分成两个问题的代码的问题,我似乎能够同时使用两种工作中的任何一种。这两个问题是从我正在使用第三方Nuget包ABCpdf的网页生成pdf,然后问题的第二部分将该电子邮件附加到发送给客户的电子邮件中。

使用ABCpdf

从html源生成pdf

pdf是使用一个像普通视图一样的网页生成的。 pdf生成器托管在azure cloudservice webrole中,并使用以下代码:

byte[] pdfBytes;
try
{
    // set Liscence key for ABCpdf
    XSettings.InstallLicense("[ABCpdf_LISCENCE_KEY]");

    using (Doc theDoc = new Doc())
    {
        // generate the pdf, I have attempted generating and transfering as stream, string, and byte[]
        MemoryStream ms = new MemoryStream();
        theDoc.HtmlOptions.Engine = EngineType.Gecko; // this allows use of most recent HTML
        theDoc.AddImageUrl(url); // this adds the page at the provided url to the document
        theDoc.Save(ms); // this creates the document itself
        pdfBytes = ms.ToArray(); // this converts it to a byte array for transport to the main application
    }
}
return Ok(pdfBytes); // return the data to the main application

在单独托管的云服务中执行ABCpdf代码是ABCpdf推荐的方法,因此我非常确定我正确地执行此操作。至少当我运行主应用程序收到的输出时,看起来像pdf的那样:

将生成的pdf附加到电子邮件

以下代码取自主应用程序,用于在将输出附加到电子邮件并发送之前调用云服务以获取pdf:

public async void SendQuotePDF(Quote quote, string fileName, string subject, string body)
{
    try
    {
        //Get pdf from cloud service hosted ABCpdf
        string requestURL = @"http://[CloudServiceURL]/api/PdfGenerator/GetWebPageInfo/?url=http://google.com"; // I'm currently just using google as a testsite to generate the pdf of
        byte[] pdfBytes = await GetPdfBytesFromUrlAsync(requestURL);

        if (pdfBytes != null)
        {
            // For each client attached to the quote
            foreach (QILT.Models.DBModels.Client c in quote.Clients)
            {
                //Get SenderEmail address and Password from settings
                string senderEmailAddress = ConfigurationManager.AppSettings.Get("SenderEmail");
                string senderPassword = ConfigurationManager.AppSettings.Get("SenderEmailPassword");

                //Create email message
                MailMessage mailMessage = new MailMessage(senderEmailAddress, c.Email);

                // Attach the generated pdf
                mailMessage.Attachments.Add(new Attachment(new MemoryStream(pdfBytes), fileName, System.Net.Mime.MediaTypeNames.Application.Pdf));
                mailMessage.IsBodyHtml = true;

                // send the email
                SmtpClient smtp = new SmtpClient();
                smtp.Host = "smtp.office365.com";
                smtp.EnableSsl = true;
                NetworkCredential NetworkCred = new NetworkCredential();
                NetworkCred.UserName = senderEmailAddress;
                NetworkCred.Password = senderPassword;
                smtp.UseDefaultCredentials = true;
                smtp.Credentials = NetworkCred;
                smtp.Port = 587;

                //Send email
                smtp.Send(mailMessage);
            }
        }
    }
}

public async System.Threading.Tasks.Task<byte[]> 
GetPdfBytesFromUrlAsync(string uri)
{
    pdfBytes = null;
    try
    {
        HttpClient httpClient = new HttpClient())
        {
            try
            {
                pdfBytes = await httpClient.GetByteArrayAsync(uri);
            }
            catch (Exception e) { e = null; }
        }
        //Return pdf as byte array
        return pdfBytes;
    }
    return null;
}

结果

从发布的站点运行此代码会发生以下情况: - 向每个客户发送电子邮件 - 电子邮件附有一个文件,在打开时,只是说“有些东西从打开时停止了”。 - API(作为主应用程序用作API)返回500内部服务器错误。这很奇怪,因为调试它到达它的最终返回语句与正常的输出数据,似乎成功完成。如果未生成/附加pdf,则输出200 ok以及它的数据模型。

我不知道在这一点上采取这个措施​​。从其他问题尝试解决方案时,我看不出任何明显错误的代码,问题的两个部分似乎都在调试器中工作,并且在代码运行期间不会抛出任何错误。我已经尝试将数据从云服务传回作为byte [],Stream和string,我已经尝试了几种可以在类型之间移动的转换方法,但无论我做什么输出和问题似乎是同样的。

Nota Bene

我不得不稍微压缩我的代码以适应这个问题,例如设置电子邮件正文等已经完成,但我只留下了与pdf相关的代码。如果你觉得我错过了任何代码段,你需要看看,请告诉我。

1 个答案:

答案 0 :(得分:1)

我遇到过这样的问题,因为我试图从非控制器类运行它。

尝试将其移至控制器类。