【问题标题】:How do I save a web page to image如何将网页保存为图像
【发布时间】:2009-03-31 15:49:55
【问题描述】:

我有一个 WebBrowser 控件,我想将查看的整个页面保存为图像(任何网页)。 我尝试使用 IHTMLElementRender 界面,但它不适用于所有网页。也许我做错了什么,因为有时快照包括滚动条,有时它只是部分的。 你有一个可以将整个网页保存到图像的工作示例吗?

谢谢。

【问题讨论】:

  • 也许你应该问“我如何截取窗口的屏幕截图(启用滚动)”。 ;-)

标签: c# .net winforms webbrowser-control mshtml


【解决方案1】:

有一个great CodeProject article 显示如何使用 IE 引擎完成此任务。如果您更喜欢使用其他浏览器的渲染引擎,这是一个开始学习的好地方。 Firefox 也有 an addon 可以执行此操作,您可以深入了解它的内部结构以了解如何在 Firefox 中完成此操作。

【讨论】:

  • 我试过用 Vista + IE8 运行它。它不起作用(捕获黑屏)。我还没调试呢。
  • 我在文章的 cmets 部分看到了一种解决方法。我也应该调查一下……
【解决方案2】:

您可以使用这些家伙http://webthumb.bluga.net/home 和以下代码。如果您每月只需要生成几张图片,它是免费的,但它们会收取更多费用。

(我与他们没有任何关系,我过去只是使用过这个)

public enum OutputType
    {
        Png,
        Jpg
    }

    public interface IWebThumbAPI
    {
        int Delay { get; set; }
        int Width { get; set; }
        int Height { get; set; }
        OutputType OutputType { get; set; }
        WebThumbAPI Get(string url);
        WebThumbAPI Get(string url, int x, int y, int width, int height);
        System.Drawing.Image SaveSize(WebThumbSize webThumbSize);
    }

    public class WebThumbAPI : IWebThumbAPI
    {
        private readonly string apiKey;
        private IList<WebThumbResponse> webThumbResponse;
        private string jobId;
        private string ApiUrl { get; set; }
        public int Delay { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public OutputType OutputType { get; set; }

        public WebThumbAPI(string apiKey)
            : this(apiKey, "")
        {
        }

        public WebThumbAPI(string apiKey, string jobId)
        {
            this.apiKey = apiKey;
            OutputType = OutputType.Png;
            Width = 1024;
            Height = 768;
            Delay = 5;
            ApiUrl = "http://webthumb.bluga.net/api.php";
            this.jobId = jobId;
        }

        public WebThumbAPI Get(string url)
        {
            return Get(url, 0, 0, 400, 200);
        }

        public WebThumbAPI Get(string url, int x, int y, int width, int height)
        {
            var outputType = OutputType == OutputType.Jpg ? "jpg" : "png";

            var doc = new XDocument(
                new XElement("webthumb",
                            new XElement("apikey", apiKey),
                             new XElement("request",
                                                 new XElement("url", url),
                                                 new XElement("outputType", outputType),
                                                 new XElement("width", Width),
                                                 new XElement("height", Height),
                                                 new XElement("delay", Delay),
                                                 new XElement("excerpt",
                                                     new XElement("x", x),
                                                     new XElement("y", y),
                                                     new XElement("width", width),
                                                     new XElement("height", height)))
                    )
                );

            var request = getRequest(doc.ToString());
            var webResponse = (HttpWebResponse)request.GetResponse();
            if (webResponse.ContentType == "text/xml")
            {
                var stream = webResponse.GetResponseStream();
                var response = XDocument.Load(XmlReader.Create(stream));
                webThumbResponse = (from xml in response.Descendants("job")
                                    select new WebThumbResponse
                                    {
                                        Estimate = (int)xml.Attribute("estimate"),
                                        Time = (DateTime)xml.Attribute("time"),
                                        Url = (string)xml.Attribute("url"),
                                        Cost = (int)xml.Attribute("cost"),
                                        Job = (string)xml.Value
                                    }).ToList();
                stream.Close();
                if (webThumbResponse.Count == 0)
                    jobId = "-1";
                else
                {
                    jobId = webThumbResponse[0].Job;
                    Thread.Sleep(webThumbResponse[0].Estimate * 1000);
                }

            }
            else
            {
                throw new InvalidOperationException("Failed request");
            }
            return this;
        }

        public System.Drawing.Image SaveSize(WebThumbSize webThumbSize)
        {
            if (jobId == "-1")
                return defaultImage(webThumbSize);
            var doc = new XDocument(
                new XElement("webthumb",
                            new XElement("apikey", apiKey),
                             new XElement("fetch",
                                                 new XElement("job", jobId),
                                                 new XElement("size", Enum.GetName(typeof(WebThumbSize), webThumbSize).ToLower())
                                                 )
                    )
                );
            var request = getRequest(doc.ToString());
            var webResponse = (HttpWebResponse)request.GetResponse();
            var stream = webResponse.GetResponseStream();

            Image image = null;
            try
            {
                image = System.Drawing.Image.FromStream(stream);
            }
            catch
            {
                image = defaultImage(webThumbSize);

            }
            return image;
        }

        private Image defaultImage(WebThumbSize webThumbSize)
        {
            var s = getSize(webThumbSize);
            var b = new Bitmap(s.Width, s.Height);
            var im = Image.FromHbitmap(b.GetHbitmap());
            var gr = System.Drawing.Graphics.FromImage(im);
            gr.Clear(Color.White);
            gr.Dispose();
            return im;
        }

        private static System.Drawing.Size getSize(WebThumbSize size)
        {
            switch (size)
            {
                case WebThumbSize.Small:
                    return new Size(80, 60);
                case WebThumbSize.Excerpt:
                    return new Size(400, 200);
                default:
                    return new Size(1, 1);
            }
        }

        private HttpWebRequest getRequest(string xml)
        {
            var request = (HttpWebRequest)WebRequest.Create(ApiUrl);
            request.Method = "POST";
            request.Timeout = 20000;
            request.ContentType = "text/xml";
            request.UserAgent = @"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3";
            request.KeepAlive = false;
            request.Pipelined = false;

            Stream newStream = request.GetRequestStream();
            var encoding = new ASCIIEncoding();
            byte[] data = encoding.GetBytes(xml);
            newStream.Write(data, 0, data.Length);
            newStream.Close();
            return request;
        }
    }

    public class WebThumbResponse
    {
        public DateTime Time;
        public string Job;
        public string Url;
        public int Cost;
        public int Estimate { get; set; }
    }

    public enum WebThumbSize
    {
        Small,
        Medium,
        Medium2,
        Large,
        Excerpt
    }

【讨论】:

    【解决方案3】:

    如果网页中大量使用 JS,例如地图应用程序,则提供的解决方案将无法正常工作。

    发现这段代码配合Webbrowser控件使用效率更高,在缺乏更好的...

    private void waitTillLoad(WebBrowser webBrowser1)
    {
       WebBrowserReadyState loadStatus;
    
       //wait till beginning of loading next page 
       int waittime = 100000;
       int counter = 0;
       while (true)
       {
           loadStatus = webBrowser1.ReadyState;
           Application.DoEvents();
    
           if ((counter > waittime) || (loadStatus == WebBrowserReadyState.Uninitialized) || (loadStatus == WebBrowserReadyState.Loading) || (loadStatus == WebBrowserReadyState.Interactive))
           {
               break;
           }
           counter++;
       }
    
       //wait till the page get loaded.
       counter = 0;
       while (true)
       {
           loadStatus = webBrowser1.ReadyState;
           Application.DoEvents();
    
           if (loadStatus == WebBrowserReadyState.Complete)
           {
               break;
           }
           counter++;
    
       }
    }
    

    感谢 QualityPoint Technologies http://qualitypoint.blogspot.com/2009/03/c-webbrowser-control-synchronization.html

    HTH!

    问候, byte_slave

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-20
      • 2011-07-17
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      相关资源
      最近更新 更多