asp.net 实现输入网址生成当前网页的图片

本文介绍了一个用于抓取网页预览图的工具,该工具能够生成指定尺寸的缩略图,并提供了不同模式下的图片缩放和裁剪功能。同时,还详细展示了如何在ASP.NET应用程序中使用这个工具。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    优快云广告是越来越多了,所有博客笔记不再更新,新网址 DotNet笔记

效果:


添加两个类:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System.Web;

namespace okpower.Utility
{
    /// <summary>
    /// 图像处理类
    /// </summary>
    public class ImageLibrary
    {
        /// <summary>
        /// 两张图片的对比结果
        /// </summary>
        public enum CompareResult
        {
            ciCompareOk,
            ciPixelMismatch,
            ciSizeMismatch
        };


        /// <summary>
        /// 对比两张图片
        /// </summary>
        /// <param name="bmp1">The first bitmap image</param>
        /// <param name="bmp2">The second bitmap image</param>
        /// <returns>CompareResult</returns>
        public static CompareResult CompareTwoImages(Bitmap bmp1, Bitmap bmp2)
        {
            CompareResult cr = CompareResult.ciCompareOk;

            //Test to see if we have the same size of image
            if (bmp1.Size != bmp2.Size)
            {
                cr = CompareResult.ciSizeMismatch;
            }
            else
            {
                //Convert each image to a byte array
                System.Drawing.ImageConverter ic =
                       new System.Drawing.ImageConverter();
                byte[] btImage1 = new byte[1];
                btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
                byte[] btImage2 = new byte[1];
                btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());

                //Compute a hash for each image
                SHA256Managed shaM = new SHA256Managed();
                byte[] hash1 = shaM.ComputeHash(btImage1);
                byte[] hash2 = shaM.ComputeHash(btImage2);

                //Compare the hash values
                for (int i = 0; i < hash1.Length && i < hash2.Length
                                  && cr == CompareResult.ciCompareOk; i++)
                {
                    if (hash1[i] != hash2[i])
                        cr = CompareResult.ciPixelMismatch;
                }
            }
            return cr;
        }        
   
        public enum ScaleMode
        {
            /// <summary>
            /// 指定高宽缩放(可能变形)
            /// </summary>
            HW,
            /// <summary>
            /// 指定宽,高按比例
            /// </summary>
            W,
            /// <summary>
            /// 指定高,宽按比例
            /// </summary>
            H,
            /// <summary>
            /// 指定高宽裁减(不变形)
            /// </summary>
            Cut
        };

        /// <summary>
        /// Resizes the image by a percentage
        /// </summary>
        /// <param name="imgPhoto">The img photo.</param>
        /// <param name="Percent">The percentage</param>
        /// <returns></returns>
        // http://www.codeproject.com/csharp/imageresize.asp
        public static Image ResizeImageByPercent(Image imgPhoto, int Percent)
        {
            float nPercent = ((float)Percent / 100);

            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;

            int destX = 0;
            int destY = 0;
            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(destWidth, destHeight,
                                     PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                                    imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }


        /// <summary>
        /// 缩放、裁切图片
        /// </summary>
        /// <param name="originalImage"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static Image ResizeImageToAFixedSize(Image originalImage, int width, int height, ScaleMode mode)
        {
            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case ScaleMode.HW:
                    break;
                case ScaleMode.W:
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case ScaleMode.H:
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case ScaleMode.Cut:
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }
            //新建一个bmp图片
            Image bitmap = new System.Drawing.Bitmap(towidth, toheight);

            //新建一个画布
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);

            //设置画布的描绘质量
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                new Rectangle(x, y, ow, oh),
                GraphicsUnit.Pixel);

            g.Dispose();

            return bitmap;
        }
       
    }
}

using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace okpower.Utility
{
    /// <summary>
    /// 供Asp.Net直接调用的包装类
    /// 作者:Kai.Ma http://kaima.cnblogs.com
    /// </summary>
    public class WebPreview 
    { 
    
        private Uri _uri = null;
        private Exception _ex = null;
        private Bitmap _bitmap = null;
        private int _timeout = 30 * 1000;//设置线程超时时长
        private int _width = 200;//缩图宽
        private int _height = 150;//缩图高
        private bool _fullPage = true;

        private WebPreview(Uri uri): this(uri, 30 * 1000, 200, 150, true)
        {

        }

        private WebPreview(Uri uri, int timeout, int width, int height, bool fullPage)
        {
            _uri = uri;
            _timeout = timeout;
            _width = width;
            _height = height;
            _fullPage = fullPage;
        }

        internal Bitmap GetWebPreview()
        {
            //Asp.Net引用Winform(类似ActiveX)控件,必须开单线程
            Thread t = new Thread(new ParameterizedThreadStart(StaRun));
            t.SetApartmentState(ApartmentState.STA);
            t.Start(this);

            if (!t.Join(_timeout))
            {
                t.Abort();
                throw new TimeoutException();
            }

            if (_ex != null) throw _ex;
            if (_bitmap == null) throw new ExecutionEngineException();
            
            return _bitmap;
        }

        public static Bitmap GetWebPreview(Uri uri)
        {
            WebPreview wp = new WebPreview(uri);
            return wp.GetWebPreview();
        }
        public static Bitmap GetWebPreview(Uri uri, int timeout, int width, int height, bool fullPage)
        {
            WebPreview wp = new WebPreview(uri,timeout,width,height,fullPage);
            return wp.GetWebPreview();
        }

        /// <summary>
        /// 为WebBrowser所开线程的启动入口函数,相当于Winform里面的Main()
        /// </summary>
        /// <param name="_wp"></param>
        private static void StaRun(object _wp)
        {
            WebPreview wp = (WebPreview)_wp;
            try
            {
                WebPreviewBase wpb = new WebPreviewBase(wp._uri,wp._width,wp._height,wp._fullPage);
                wp._bitmap = wpb.GetWebPreview();
            }
            catch (Exception ex)
            {
                wp._ex = ex;
            }
        }
    }

    /// <summary>
    /// 包装后的抓图基类。WebBrowser自带的BrawToBitmap不能抓到一些网站的图片,
    /// 对于一些转向的网站会返回空白图片,所以采用原生的通过IViewObject接口
    /// 取浏览器的图象,实现SNAP。感谢类库的作者“随飞”。
    /// 原作者:随  飞 http://chinasf.cnblogs.com
    /// 包装者:Kai.Ma http://kaima.cnblogs.com
    /// </summary>
    class WebPreviewBase: IDisposable
    {
        Uri _uri = new Uri("about:blank");//原始uri
        int _thumbW = 1024;     //缩略图高度
        int _thumbH = 768;      //缩略图宽度
        WebBrowser _wb;         //浏览器对象
        bool _fullpage = false; //是否抓取全图


        public WebPreviewBase(Uri uri, int thumbW, int thumbH, bool fullpage)
        {
            _wb = new WebBrowser();
            _wb.ScriptErrorsSuppressed = true;
            //_wb.ScriptErrorsSuppressed = false;
            _wb.ScrollBarsEnabled = false;
            _wb.Size = new Size(1024, 768);//浏览器分辨率为1024x768            
            _wb.NewWindow += new System.ComponentModel.CancelEventHandler(CancelEventHandler);
            _thumbW = thumbW;
            _thumbH = thumbH;
            _uri = uri;
        }
        /// <summary>
        /// URI 地址
        /// </summary>
        public Uri Uri
        {
            get { return _uri; }
            set { _uri = value; }
        }
        /// <summary>
        /// 缩略图宽度
        /// </summary>
        public int ThumbW
        {
            get { return _thumbW; }
            set { _thumbW = value; }
        }
        /// <summary>
        /// 缩略图高度
        /// </summary>
        public int ThumbH
        {
            get { return _thumbH; }
            set { _thumbH = value; }
        }
        //防止弹窗
        public void CancelEventHandler(object sender,System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
        }
        /// <summary>
        /// 初始化
        /// </summary>
        protected void InitComobject()
        {
            try
            {
                _wb.Navigate(this._uri);
                //因为没有窗体,所以必须如此
                while (_wb.ReadyState != WebBrowserReadyState.Complete)
                {
                    //立即重绘
                    Application.DoEvents();
                }
                //这句最好注释,不然网页上的动画都抓不到了
                _wb.Stop();
                if (_wb.ActiveXInstance == null) throw new Exception("实例不能为空");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取Web预览图
        /// </summary>
        /// <returns>Bitmap</returns>
        public Bitmap GetWebPreview()
        {
            #region 调整图片高宽,并调整浏览器高宽适应图片高宽
            int w = _wb.Width;
            int h = _wb.Height;
            Size sz = _wb.Size;

            if (_fullpage)
            {
                h = _wb.Document.Body.ScrollRectangle.Height; // +SystemInformation.VerticalScrollBarWidth;
                w = _wb.Document.Body.ScrollRectangle.Width; // +SystemInformation.HorizontalScrollBarHeight;
            }

            // 最小宽度不能小于缩略图宽度
            if (w < _thumbW)
                w = _thumbW;

            // 调整最小高度,充满浏览器
            if (h < sz.Height)
                h = sz.Height;
            _wb.Size = new Size(w, h);
            #endregion

            try
            {
                InitComobject();
                //构造snapshot类,抓取浏览器ActiveX的图象
                Snapshot snap = new Snapshot();
                Bitmap thumBitmap = snap.TakeSnapshot(_wb.ActiveXInstance, new Rectangle(0, 0, w, h));
                //调整图片大小,这里选择以宽度为标准,高度保持比例
                thumBitmap = (Bitmap)ImageLibrary.ResizeImageToAFixedSize(thumBitmap, _thumbW, _thumbH, ImageLibrary.ScaleMode.W);
                return thumBitmap;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Dispose()
        {
            _wb.Dispose();
        }

    }


    #region WebPreview的类库
    /// <summary>
    /// ActiveX 组件快照类
    /// AcitveX 必须实现 IViewObject 接口
    /// 
    /// 作者:随飞
    /// http://chinasf.cnblogs.com
    /// chinasf@hotmail.com
    /// </summary>
    class Snapshot
    {
        /// <summary>
        /// 取快照
        /// </summary>
        /// <param name="pUnknown">Com 对象</param>
        /// <param name="bmpRect">图象大小</param>
        /// <returns></returns>
        public Bitmap TakeSnapshot(object pUnknown, Rectangle bmpRect)
        {
            if (pUnknown == null)
                return null;
            //必须为com对象
            if (!Marshal.IsComObject(pUnknown))
                return null;
            //IViewObject 接口
            UnsafeNativeMethods.IViewObject ViewObject = null;
            IntPtr pViewObject = IntPtr.Zero;
            //内存图
            Bitmap pPicture = new Bitmap(bmpRect.Width, bmpRect.Height);
            Graphics hDrawDC = Graphics.FromImage(pPicture);
            //获取接口
            object hret = Marshal.QueryInterface(Marshal.GetIUnknownForObject(pUnknown),
                ref UnsafeNativeMethods.IID_IViewObject, out pViewObject);
            try
            {
                ViewObject = Marshal.GetTypedObjectForIUnknown(pViewObject, typeof(UnsafeNativeMethods.IViewObject)) as UnsafeNativeMethods.IViewObject;
                //调用Draw方法
                ViewObject.Draw((int)DVASPECT.DVASPECT_CONTENT,
                    -1,
                    IntPtr.Zero,
                    null,
                    IntPtr.Zero,
                    hDrawDC.GetHdc(),
                    new NativeMethods.COMRECT(bmpRect),
                    null,
                    IntPtr.Zero,
                    0);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw ex;
            }
            //释放
            hDrawDC.Dispose();
            return pPicture;
        }
    }

    /// <summary>
    /// 从 .Net 2.0 的 System.Windows.Forms.Dll 库提取
    /// 版权所有:微软公司
    /// </summary>
    internal static class NativeMethods
    {
        [StructLayout(LayoutKind.Sequential)]
        public sealed class tagDVTARGETDEVICE
        {
            [MarshalAs(UnmanagedType.U4)]
            public int tdSize;
            [MarshalAs(UnmanagedType.U2)]
            public short tdDriverNameOffset;
            [MarshalAs(UnmanagedType.U2)]
            public short tdDeviceNameOffset;
            [MarshalAs(UnmanagedType.U2)]
            public short tdPortNameOffset;
            [MarshalAs(UnmanagedType.U2)]
            public short tdExtDevmodeOffset;
        }

        [StructLayout(LayoutKind.Sequential)]
        public class COMRECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
            public COMRECT()
            {
            }

            public COMRECT(Rectangle r)
            {
                this.left = r.X;
                this.top = r.Y;
                this.right = r.Right;
                this.bottom = r.Bottom;
            }

            public COMRECT(int left, int top, int right, int bottom)
            {
                this.left = left;
                this.top = top;
                this.right = right;
                this.bottom = bottom;
            }

            public static NativeMethods.COMRECT FromXYWH(int x, int y, int width, int height)
            {
                return new NativeMethods.COMRECT(x, y, x + width, y + height);
            }

            public override string ToString()
            {
                return string.Concat(new object[] { "Left = ", this.left, " Top ", this.top, " Right = ", this.right, " Bottom = ", this.bottom });
            }

        }

        [StructLayout(LayoutKind.Sequential)]
        public sealed class tagLOGPALETTE
        {
            [MarshalAs(UnmanagedType.U2)]
            public short palVersion;
            [MarshalAs(UnmanagedType.U2)]
            public short palNumEntries;
        }
    }

    /// <summary>
    /// 从 .Net 2.0 的 System.Windows.Forms.Dll 库提取
    /// 版权所有:微软公司
    /// </summary>
    [SuppressUnmanagedCodeSecurity]
    internal static class UnsafeNativeMethods
    {
        public static Guid IID_IViewObject = new Guid("{0000010d-0000-0000-C000-000000000046}");

        [ComImport, Guid("0000010d-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IViewObject
        {
            [PreserveSig]
            int Draw([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] NativeMethods.tagDVTARGETDEVICE ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [In] NativeMethods.COMRECT lprcBounds, [In] NativeMethods.COMRECT lprcWBounds, IntPtr pfnContinue, [In] int dwContinue);
            [PreserveSig]
            int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] NativeMethods.tagDVTARGETDEVICE ptd, IntPtr hicTargetDev, [Out] NativeMethods.tagLOGPALETTE ppColorSet);
            [PreserveSig]
            int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze);
            [PreserveSig]
            int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze);
            void SetAdvise([In, MarshalAs(UnmanagedType.U4)] int aspects, [In, MarshalAs(UnmanagedType.U4)] int advf, [In, MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);
            void GetAdvise([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] paspects, [In, Out, MarshalAs(UnmanagedType.LPArray)] int[] advf, [In, Out, MarshalAs(UnmanagedType.LPArray)] IAdviseSink[] pAdvSink);
        }
    }
    #endregion 
}

页面中使用方式:

default.aspx页面代码:

    <div>
        网址<asp:TextBox ID="TextBox1" runat="server" Width="427px">http://</asp:TextBox>
        <asp:Button ID="bt" runat="server" OnClick="bt_Click" Text="抓取" /><br />
        <br />
        <div id="Preview" runat="server"></div>
    </div>
对应的cs代码:

using okpower.Utility;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace HtmlToImg
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            
        }

        public string WebPreview(string url)
        {
            if (string.IsNullOrEmpty(url)) return string.Empty;
            string fold = "_images/";//图片存放目录
            string physicsFold = Server.MapPath(fold);
            string name = url;
            name = name.Replace('/', '-');
            name = name.Replace(':', '_');
            name = name.Replace('&', '_');
            name = name.Replace(',', '_');
            name = name.Replace('\'', '_');
            name = name.Replace('"', '_');
            string fileName = name + ".jpg";
            if (!System.IO.File.Exists(physicsFold + fileName))
            {
                try
                {
                    Bitmap image = okpower.Utility.WebPreview.GetWebPreview(new Uri(url));

                    //保存图片数据
                    image.Save(physicsFold + fileName, ImageFormat.Jpeg);
                }
                catch (Exception ee)
                {
                    throw;
                }
            }
            return fold + fileName;
        }

        protected void bt_Click(object sender, EventArgs e)
        {
            this.Preview.InnerHtml = "<img src=\"" + WebPreview(TextBox1.Text) + "\"/>";
        }
    }
}

效果图如顶部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值