【问题标题】:Convert HTML string to image将 HTML 字符串转换为图像
【发布时间】:2013-07-23 19:52:38
【问题描述】:

我有一个包含 HTML 标记的字符串变量。这个 HTML 标记基本上代表了电子邮件的内容。

现在我想从这个字符串内容创建一个实际包含 HTML 标记的图像。 我不想通过将此内容写入其中来创建 HTML 文件。我只想用这个字符串创建一个图像文件。

这是我所拥有的:

string emailBody="<html><head></head><body><p>This is my text<p>...</body</html>"

如何从这个emailBody 字符串内容创建图像?

【问题讨论】:

标签: c# html asp.net


【解决方案1】:

感谢大家的回复。我使用HtmlRenderer 外部dll(库)来实现相同的功能,并在code 下方找到了相同的功能。

这是代码

public void ConvertHtmlToImage()
{
   Bitmap m_Bitmap = new Bitmap(400, 600);
   PointF point = new PointF(0, 0);
   SizeF maxSize = new System.Drawing.SizeF(500, 500);
   HtmlRenderer.HtmlRender.Render(Graphics.FromImage(m_Bitmap),
                                           "<html><body><p>This is some html code</p>"
                                           + "<p>This is another html line</p></body>",
                                            point, maxSize);

   m_Bitmap.Save(@"C:\Test.png", ImageFormat.Png);
}

【讨论】:

  • 为什么这个答案没有得到更多的支持?对我来说几乎完美无缺(除了我必须对图像分辨率进行一些微调)?
  • 使用 HtmlRenderer.HtmlRender.RenderGdiPlus 代替,否则看起来不太好。
  • 我尝试使用上述引用 htmlrenderer 程序集的代码。但它不起作用。无法识别程序集。我尝试将命名空间用作“使用 TheArtOfDev.HtmlRenderer”
  • subash,你还需要添加HtmlRenderer,WinForms 然后使用TheArtOfDev.HtmlRenderer.WinForms.HtmlRender.RenderToImage
  • 我在我的asp.net web应用程序中添加了HtmlRenderer.Core dll,但没有可用的HtmlRenderer.HtmlRender.Render方法。
【解决方案2】:

尝试以下方法:

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

class Program
{
    static void Main(string[] args)
    {
        var source =  @"
        <!DOCTYPE html>
        <html>
            <body>
                <p>An image from W3Schools:</p>
                <img 
                    src=""http://www.w3schools.com/images/w3schools_green.jpg"" 
                    alt=""W3Schools.com"" 
                    width=""104"" 
                    height=""142"">
            </body>
        </html>";
        StartBrowser(source);
        Console.ReadLine();
    }

    private static void StartBrowser(string source)
    {
        var th = new Thread(() =>
        {
            var webBrowser = new WebBrowser();
            webBrowser.ScrollBarsEnabled = false;
            webBrowser.DocumentCompleted +=
                webBrowser_DocumentCompleted;
            webBrowser.DocumentText = source;
            Application.Run();
        });
        th.SetApartmentState(ApartmentState.STA);
        th.Start();
    }

    static void 
        webBrowser_DocumentCompleted(
        object sender, 
        WebBrowserDocumentCompletedEventArgs e)
    {
        var webBrowser = (WebBrowser)sender;
        using (Bitmap bitmap = 
            new Bitmap(
                webBrowser.Width, 
                webBrowser.Height))
        {
            webBrowser
                .DrawToBitmap(
                bitmap, 
                new System.Drawing
                    .Rectangle(0, 0, bitmap.Width, bitmap.Height));
            bitmap.Save(@"filename.jpg", 
                System.Drawing.Imaging.ImageFormat.Jpeg);
        }
    }
}

注意:感谢 Hans Passant 他在问题 WebBrowser Control in a new thread 上的出色表现 answer 启发了这个解决方案。

【讨论】:

  • 这对我来说已经很长时间了。刚刚发现了一个限制。在 css 中通过 @font-face 访问的下载字体不会被渲染。
  • 我不相信这在 .net 核心中可用。它似乎只在框架中
  • @Paul Evans 你有没有找到可以解决这个问题的解决方案?
  • 简单的概念!有谁知道如何扩展此解决方案,以将整个页面放入输出图像中,即使页面的高度大于图像的高度?
【解决方案3】:

所以我想到了这个,我想我会将我的最新解决方案发布给任何搜索类似内容的人。

我使用了(开源)Puppeteer Sharp (v3) 结果如下所示:

public class ImageRenderer : IDisposable
    {
        private BrowserFetcher _browserFetcher;

        public ImageRenderer()
        {
            _browserFetcher = new BrowserFetcher();
        }

        public async Task<byte[]> RenderImageDataAsync(string html)
        {
            try
            {
                // Download chrome (headless) browser (first time takes a while).
                await _browserFetcher.DownloadAsync();

                // Launch the browser and set the given html.
                await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
                await using var page = await browser.NewPageAsync();
                await page.SetContentAsync(html);

                // Select the element and take a screen-shot, or just use the page, for example: page.ScreenshotDataAsync()
                var elementQuery = "#myElementId";
                await page.WaitForSelectorAsync(elementQuery, new WaitForSelectorOptions { Timeout = 2000 }); // Wait for the selector to load.

                var elementHandle = await page.QuerySelectorAsync(elementQuery); // Declare a variable with an ElementHandle.
                var result = await elementHandle.ScreenshotDataAsync(
                    new ScreenshotOptions
                    {
                        Type = ScreenshotType.Png
                        // Quality = Not supported with PNG images!
                    }
                );

                await browser.CloseAsync();
                return result;
            }
            catch (Exception ex)
            {
                // Log ex $"{nameof(RenderImageDataAsync)}: Unable to render image from {nameof(html)}={html}");
            }

            return null;
        }

        public void Dispose()
        {
            _browserFetcher = null;
        }
    }
  • 专业版:使用真正的浏览器;
  • 缺点:使用真正的浏览器; _browserFetcher.DownloadAsync(); 将为此下载(到文件夹 .local-chromium)大约 380MB 的文件。

【讨论】:

    【解决方案4】:
           <!--ForExport data in iamge -->
            <script type="text/javascript">
                function ConvertToImage(btnExport) {
                    html2canvas($("#dvTable")[0]).then(function (canvas) {
                        var base64 = canvas.toDataURL();
                        $("[id*=hfImageData]").val(base64);
                        __doPostBack(btnExport.name, "");
                    });
                    return false;
                }
            </script>
    
            <!--ForExport data in iamge -->
    
            <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
            <script src="../js/html2canvas.min.js"></script> 
    
    
    
    
    
    <table>
                    <tr>
                        <td valign="top">
                            <asp:Button ID="btnExport" Text="Download Back" runat="server" UseSubmitBehavior="false"
                                OnClick="ExportToImage" OnClientClick="return ConvertToImage(this)" />
                            <div id="dvTable" class="divsection2" style="width: 350px">
                                <asp:HiddenField ID="hfImageData" runat="server" />
                                <table width="100%">
                                    <tr>
                                        <td>
                                            <br />
    
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <asp:Label ID="Labelgg" runat="server" CssClass="labans4" Text=""></asp:Label>
                                        </td>
                                    </tr>
    
                                </table>
                            </div>
                        </td>
                    </tr>
                </table>
    
    
             protected void ExportToImage(object sender, EventArgs e)
                    {
                        string base64 = Request.Form[hfImageData.UniqueID].Split(',')[1];
                        byte[] bytes = Convert.FromBase64String(base64);
                        Response.Clear();
                        Response.ContentType = "image/png";
                        Response.AddHeader("Content-Disposition", "attachment; filename=name.png");
                        Response.Buffer = true;
                        Response.Cache.SetCacheability(HttpCacheability.NoCache);
                        Response.BinaryWrite(bytes);
                        Response.End();
    
                    }
    

    【讨论】:

    • OP 显然是在寻求一种在 C# ASP.Net 中实现它的方法,而不是在浏览器中。
    猜你喜欢
    • 2018-09-07
    • 2019-02-12
    • 2014-07-21
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2014-08-29
    相关资源
    最近更新 更多