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

Generating a pdf from html and attaching it to an email

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

使用 ABCpdfhtml 从 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;
}

结果

运行 此代码来自已发布的站点,出现以下情况: - 向每个客户发送一封电子邮件 - 电子邮件附有一个文件,打开时,只显示 "something stopped this from opening"。 - API(因为主应用程序作为 API 运行)returns 500 内部服务器错误。这是 st运行ge,因为在调试时它到达了具有正常输出数据的最终 return 语句并且似乎已成功完成。使用 pdf 不是 generated/attached 它输出 200 ok 以及它的数据模型。

我现在不确定该把它带到哪里。通过尝试其他问题的解决方案,我看不出代码有任何明显的错误,问题的两个部分似乎都在调试器中工作,并且在代码的 运行 期间没有抛出任何错误。我已经尝试将数据作为字节[]、流和字符串从云服务传回,并且我已经尝试了几乎所有我能找到的用于在类型之间移动的转换方法,但无论我做什么,输出和问题似乎都是一样。

诺塔贝内

我不得不稍微压缩我的代码以适应这个问题,设置电子邮件正文等事情已经完成,但我只留下了与 pdf 相关的代码。如果您觉得我遗漏了任何代码部分并且您需要查看,请告诉我。

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

尝试将其移动到控制器 class。