■ 파비콘 다운로드 하기

----------------------------------------------------------------------------------------------------


DownloadFavicon.zip


MainForm.cs

 

 

using System;

using System.IO;

using System.Windows.Forms;

 

namespace DownloadFavicon

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            this.downloadButton.Click += downloadButton_Click;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Download 버튼 클릭시 처리하기 - downloadButton_Click(sender, e)

 

        /// <summary>

        /// Download 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void downloadButton_Click(object sender, EventArgs e)

        {

            #region 사이트 URL을 설정한다.

 

            string siteURL = this.siteURLTextBox.Text.Trim();

 

            if(string.IsNullOrWhiteSpace(siteURL))

            {

                MessageBox.Show("사이트 URL을 입력해 주시기 바랍니다.");

 

                this.siteURLTextBox.Focus();

 

                this.siteURLTextBox.SelectAll();

 

                return;

            }

 

            if(!siteURL.StartsWith("http://") && !siteURL.StartsWith("https://"))

            {

                MessageBox.Show("사이트 URL은 \"http://\" 또는 \"https://\" 문자열로 시작해야 합니다.");

 

                this.siteURLTextBox.Focus();

 

                this.siteURLTextBox.SelectAll();

 

                return;

            }

 

            #endregion

            #region 파비콘 URI를 설정한다.

 

            Uri favionUri = FaviconHelper.GetFaviconURL(siteURL);

 

            if(favionUri == null)

            {

                MessageBox.Show("입력한 사이트 URL로 파비콘 URL을 설정할 수 없습니다.");

 

                this.siteURLTextBox.Focus();

 

                this.siteURLTextBox.SelectAll();

 

                return;

            }

 

            #endregion

            #region 다운로드 경로를 설정한다.

 

            string downloadPath = this.downloadPathTextBox.Text.Trim();

 

            if(string.IsNullOrWhiteSpace(downloadPath))

            {

                MessageBox.Show("다운로드 경로를 입력해 주시기 바랍니다");

 

                this.downloadPathTextBox.Focus();

 

                this.downloadPathTextBox.SelectAll();

 

                return;

            }

 

            if(Directory.Exists(downloadPath))

            {

                try

                {

                    Directory.CreateDirectory(downloadPath);

                }

                catch

                {

                    MessageBox.Show("다운로드 경로 생성시 에러가 발생했습니다.");

 

                    this.downloadPathTextBox.Focus();

 

                    this.downloadPathTextBox.SelectAll();

 

                    return;

                }

            }

 

            #endregion

 

            string downloadFilePath = Path.Combine(downloadPath, favionUri.Host + ".ico");

 

            FaviconHelper.DownloadFaviconFile(siteURL, downloadFilePath);

        }

 

        #endregion

    }

}

 

 

FaviconHelper.cs

 

 

using System;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Drawing.Imaging;

using System.IO;

using System.Linq;

using System.Net;

 

using HtmlAgilityPack;

 

namespace DownloadFavicon

{

    /// <summary>

    /// 파비콘 헬퍼

    /// </summary

    /// <remarks>

    public class FaviconHelper

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 타임 아웃

        /// </summary>

        private static int _timeOut = 5000;

 

        private static string _userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +

                                           "AppleWebKit/537.36 (KHTML, like Gecko) "    +

                                           "Chrome/42.0.2311.135 Safari/537.36 Edge/12.246";

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 파비콘 URL구하기 - GetFaviconURL(siteURL)

 

        /// <summary>

        /// 파비콘 URL구하기

        /// </summary>

        /// <param name="siteURL">사이트 URL</param>

        /// <returns>파비콘 URL</returns>

        public static Uri GetFaviconURL(string siteURL)

        {

            Uri siteUri    = null;

            Uri faviconUri = null;

 

            try

            {

                string leftPart = new Uri(siteURL).GetLeftPart(UriPartial.Authority);

 

                siteUri = new Uri(leftPart);

            }

            catch

            {

                return null;

            }

 

            try

            {

                HtmlWeb htmlWeb = new HtmlWeb();

 

                htmlWeb.UserAgent  = _userAgent;

                htmlWeb.PreRequest = delegate(HttpWebRequest httpWebRequest)

                {

                    httpWebRequest.Timeout = _timeOut;

 

                    return true;

                };

 

                HtmlDocument htmlDocument = htmlWeb.Load(siteUri.ToString());

 

                siteUri = htmlWeb.ResponseUri;

 

                HtmlNodeCollection htmlNodeCollection = htmlDocument.DocumentNode.SelectNodes("//link");

 

                if(htmlNodeCollection != null)

                {

                    foreach(HtmlNode htmlNode in htmlNodeCollection)

                    {

                        HtmlAttribute relHtmlAttribute = GetHtmlAttribute(htmlNode, "rel");

 

                        if(relHtmlAttribute == null)

                        {

                            continue;

                        }

 

                        if(relHtmlAttribute.Value.IndexOf("icon", StringComparison.InvariantCultureIgnoreCase) > 0)

                        {

                            HtmlAttribute hrefHtmlAttribute = GetHtmlAttribute(htmlNode, "href");

 

                            if(hrefHtmlAttribute == null)

                            {

                                continue;

                            }

 

                            if(hrefHtmlAttribute.Value.StartsWith("data:", StringComparison.InvariantCultureIgnoreCase))

                            {

                                continue;

                            }

 

                            if(hrefHtmlAttribute.Value.StartsWith("//", StringComparison.InvariantCultureIgnoreCase))

                            {

                                faviconUri = new Uri(siteUri.Scheme + ":" + hrefHtmlAttribute.Value);

 

                                break;

                            }

 

                            Uri        absoluteUri;

                            UriBuilder uriBuilder;

 

                            if(Uri.TryCreate(hrefHtmlAttribute.Value, UriKind.Absolute, out absoluteUri))

                            {

                                if(string.Compare(absoluteUri.Scheme, "file", true) == 0)

                                {

                                    uriBuilder = new UriBuilder(absoluteUri);

 

                                    uriBuilder.Scheme = siteUri.Scheme;

 

                                    absoluteUri = uriBuilder.Uri;

                                }

 

                                faviconUri = absoluteUri;

 

                                break;

                            }

 

                            uriBuilder = new UriBuilder();

 

                            uriBuilder.Scheme = siteUri.Scheme;

                            uriBuilder.Host   = siteUri.Host;

                            uriBuilder.Path   = hrefHtmlAttribute.Value;

 

                            Uri relativeUri = uriBuilder.Uri;

 

                            faviconUri = relativeUri;

 

                            break;

                        }

                    }

                }

            }

            catch

            {

            }

 

            if(faviconUri == null)

            {

                try

                {

                    Uri alternateFaviconUri = new Uri(string.Format("{0}://{1}/favicon.ico", siteUri.Scheme, siteUri.Host));

 

                    WebRequest webRequest = WebRequest.Create(alternateFaviconUri);

 

                    webRequest.Timeout = _timeOut;

                    webRequest.Method  = "HEAD";

 

                    using(HttpWebResponse httpWebResponse = webRequest.GetResponse() as HttpWebResponse)

                    {

                        if(httpWebResponse != null && httpWebResponse.StatusCode == HttpStatusCode.OK)

                        {

                            faviconUri = alternateFaviconUri;

                        }

                    }

                }

                catch

                {

                }

            }

 

            return faviconUri;

        }

 

        #endregion

        #region 파비콘 파일 다운로드 하기 - DownloadFaviconFile(siteURL, targetFile)

 

        /// <summary>

        /// 파비콘 파일 다운로드 하기

        /// </summary>

        /// <param name="siteURL">사이트 URL</param>

        /// <param name="targetFile">타겟 파일</param>

        /// <returns>처리 결과</returns>

        public static bool DownloadFaviconFile(string siteURL, string targetFile)

        {

            TimeoutWebClient webClient = new TimeoutWebClient();

 

            Uri faviconURL = GetFaviconURL(siteURL);

 

            bool result = false;

 

            if(faviconURL != null)

            {

                webClient.Headers[HttpRequestHeader.UserAgent] = _userAgent;

 

                byte[] bufferArray = new byte[0];

 

                try

                {

                    bufferArray = webClient.DownloadData(faviconURL);

                }

                catch

                {

                }

 

                if(bufferArray.Length > 0)

                {

                    ImageConverter imageConverter = new ImageConverter();

 

                    if(imageConverter.IsValid(bufferArray))

                    {

                        IconConverter iconConverter = new IconConverter();

 

                        if(iconConverter.IsValid(bufferArray))

                        {

                            Icon temporaryIcon = iconConverter.ConvertFrom(bufferArray) as Icon;

 

                            Icon resizedIcon = new Icon(temporaryIcon, 24, 24);

 

                            Bitmap temporaryBitmap = resizedIcon.ToBitmap();

 

                            Bitmap finalBitmap;

 

                            if(temporaryBitmap.Width > 24)

                            {

                                finalBitmap = ResizeImage(temporaryBitmap, 24, 24);

                            }

                            else

                            {

                                finalBitmap = temporaryBitmap;

                            }

 

                            Icon finalIcon = GetIcon(finalBitmap);

 

                            try

                            {

                                using(Stream iconStream = File.OpenWrite(targetFile))

                                {

                                    finalIcon.Save(iconStream);

 

                                    result = true;

                                }

 

                            }

                            catch

                            {

                            }

                        }

                        else

                        {

                            Bitmap finalBitmap;

 

                            Image temporaryImage = imageConverter.ConvertFrom(bufferArray) as Image;

 

                            if(temporaryImage.Width >= 8)

                            {

                                if(temporaryImage.Width > 24)

                                {

                                    finalBitmap = ResizeImage(temporaryImage, 24, 24);

                                }

                                else

                                {

                                    finalBitmap = new Bitmap(temporaryImage);

                                }

 

                                finalBitmap.Save(targetFile);

 

                                result = true;

                            }

                        }

                    }

                }

            }

 

            if(!result)

            {

                byte[] bufferArray = new byte[0];

 

                try

                {

                    string alternateURL = "http://www.google.com/s2/favicons?domain_url=" + Uri.EscapeDataString(siteURL);

 

                    bufferArray = webClient.DownloadData(alternateURL);

 

                    if(bufferArray.Length > 0)

                    {

                        long checksum = GetChecksum(bufferArray);

 

                        if(checksum != 87073 && checksum != 59260)

                        {

                            ImageConverter imageConverter = new ImageConverter();

 

                            Image temporaryImage = imageConverter.ConvertFrom(bufferArray) as Image;

 

                            Bitmap temporaryBitmap = new Bitmap(temporaryImage);

 

                            Icon finalIcon = GetIcon(temporaryBitmap);

 

                            try

                            {

                                using(Stream iconStream = File.OpenWrite(targetFile))

                                {

                                    finalIcon.Save(iconStream);

 

                                    result = true;

                                }

                            }

                            catch

                            {

                            }

                        }

                    }

                }

                catch

                {

                }

            }

 

            webClient.Dispose();

 

            return result;

        }

 

        #endregion

        #region 아이콘 생성하기 - CreateIcon(graphicFilePath, targetFilePath)

 

        /// <summary>

        /// 아이콘 생성하기

        /// </summary>

        /// <param name="graphicFilePath">그래픽 파일 경로</param>

        /// <param name="targetFilePath">타겟 파일 경로</param>

        /// <returns>처리 결과</returns>

        public static bool CreateIcon(string graphicFilePath, string targetFilePath)

        {

            byte[] bufferArray = new byte[0];

            bool   result      = false;

 

            try

            {

                bufferArray = File.ReadAllBytes(graphicFilePath);

 

                if(bufferArray.Length > 0)

                {

                    ImageConverter imageConverter = new ImageConverter();

 

                    if(imageConverter.IsValid(bufferArray))

                    {

                        IconConverter iconConverter = new IconConverter();

 

                        if(iconConverter.IsValid(bufferArray))

                        {

                            Icon temporaryIcon = iconConverter.ConvertFrom(bufferArray) as Icon;

 

                            Icon resizedIcon = new Icon(temporaryIcon, 24, 24);

 

                            Bitmap temporaryBitmap = resizedIcon.ToBitmap();

 

                            Bitmap finalBitmap;

 

                            if(temporaryBitmap.Width > 24)

                            {

                                finalBitmap = ResizeImage(temporaryBitmap, 24, 24);

                            }

                            else

                            {

                                finalBitmap = temporaryBitmap;

                            }

 

                            Icon finalIcon = GetIcon(finalBitmap);

 

                            try

                            {

                                using(Stream iconStream = File.OpenWrite(targetFilePath))

                                {

                                    finalIcon.Save(iconStream);

 

                                    result = true;

                                }

                            }

                            catch

                            {

                            }

                        }

                        else

                        {

                            Bitmap finalBitmap;

 

                            Image temporaryImage = imageConverter.ConvertFrom(bufferArray) as Image;

 

                            if(temporaryImage.Width >= 8)

                            {

                                if(temporaryImage.Width > 24)

                                {

                                    finalBitmap = ResizeImage(temporaryImage, 24, 24);

                                }

                                else

                                {

                                    finalBitmap = new Bitmap(temporaryImage);

                                }

 

                                finalBitmap.Save(targetFilePath);

 

                                result = true;

                            }

                        }

                    }

                }

            }

            catch

            {

            }

 

            return result;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region HTML 어트리뷰트 구하기 - GetHtmlAttribute(htmlNode, attributeName)

 

        /// <summary>

        /// HTML 어트리뷰트 구하기

        /// </summary>

        /// <param name="htmlNode">HTML 노드</param>

        /// <param name="attributeName">어트리뷰트명</param>

        /// <returns>HtmlAttribute</returns>

        private static HtmlAttribute GetHtmlAttribute(HtmlNode htmlNode, string attributeName)

        {

            return htmlNode.Attributes.FirstOrDefault(x => x.Name.Equals(attributeName,

                StringComparison.InvariantCultureIgnoreCase));

        }

 

        #endregion

        #region 이미지 크기 변경하기 - ResizeImage(sourceImage, targetWidth, targetHeight)

 

        /// <summary>

        /// 이미지 크기 변경하기

        /// </summary>

        /// <param name="sourceImage">소스 이미지</param>

        /// <param name="targetWidth">타겟 너비</param>

        /// <param name="targetHeight">타겟 높이</param>

        /// <returns>비트맵</returns>

        private static Bitmap ResizeImage(Image sourceImage, int targetWidth, int targetHeight)

        {

            Rectangle targetRectangle = new Rectangle(0, 0, targetWidth, targetHeight);

            Bitmap    targetBitmap    = new Bitmap(targetWidth, targetHeight);

 

            targetBitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);

 

            using(Graphics targetGraphics = Graphics.FromImage(targetBitmap))

            {

                targetGraphics.CompositingMode    = CompositingMode.SourceCopy;

                targetGraphics.CompositingQuality = CompositingQuality.HighQuality;

                targetGraphics.InterpolationMode  = InterpolationMode.HighQualityBicubic;

                targetGraphics.SmoothingMode      = SmoothingMode.HighQuality;

                targetGraphics.PixelOffsetMode    = PixelOffsetMode.HighQuality;

 

                using(ImageAttributes targetImageAttributes = new ImageAttributes())

                {

                    targetImageAttributes.SetWrapMode(WrapMode.TileFlipXY);

 

                    targetGraphics.DrawImage(sourceImage, targetRectangle, 0, 0, sourceImage.Width,

                        sourceImage.Height, GraphicsUnit.Pixel, targetImageAttributes);

                }

            }

 

            return targetBitmap;

        }

 

        #endregion

        #region 아이콘 구하기 - GetIcon(sourceBitmap)

 

        /// <summary>

        /// 아이콘 구하기

        /// </summary>

        /// <param name="sourceBitmap">소스 비트맵</param>

        /// <returns>아이콘</returns>

        private static Icon GetIcon(Bitmap sourceBitmap)

        {

            Icon targetIcon = null;

 

            MemoryStream sourceMemoryStream = new MemoryStream();

 

            sourceBitmap.Save(sourceMemoryStream, ImageFormat.Png);

 

            MemoryStream targetMemoryStream = new MemoryStream();

 

            BinaryWriter binaryWriter = new BinaryWriter(targetMemoryStream);

 

            // 0-1 예약, 0

            binaryWriter.Write((byte)0);

            binaryWriter.Write((byte)0);

            // 2-3 이미지 타입 : 1 = 아이콘, 2 = 커서

            binaryWriter.Write((short)1);

            // 4-5 이미지 수

            binaryWriter.Write((short)1);

            // 이미지 엔트리 1

            // 0 이미지 너비

            binaryWriter.Write((byte)sourceBitmap.Width);

            // 1 이미지 높이

            binaryWriter.Write((byte)sourceBitmap.Height);

            // 2 컬러 수

            binaryWriter.Write((byte)0);

            // 3 예약

            binaryWriter.Write((byte)0);

            // 4-5 색상 플레인

            binaryWriter.Write((short)0);

            // 6-7 픽셀 당 비트 수

            binaryWriter.Write((short)32);

            // 8-11 이미지 데이터 크기

            binaryWriter.Write((int)sourceMemoryStream.Length);

            // 12-15 이미지 데이터 오프셋

            binaryWriter.Write((int)(6 + 16));

            // 이미지 데이터 쓰기

            // PNG 데이터는 전체 PNG 데이터 파일을 포함해야 한다.

            binaryWriter.Write(sourceMemoryStream.ToArray());

 

            binaryWriter.Flush();

 

            targetMemoryStream.Position = 0;

 

            targetIcon = new Icon(targetMemoryStream);

 

            sourceMemoryStream.Close();

 

            binaryWriter.Close();

 

            return targetIcon;

        }

 

        #endregion

        #region 체크썸 구하기 - GetChecksum(byteArray)

 

        /// <summary>

        /// 체크썸 구하기

        /// </summary>

        /// <param name="byteArray">바이트 배열</param>

        /// <returns>체크썸</returns>

        private static long GetChecksum(byte[] byteArray)

        {

            long checksum = 0;

 

            foreach(byte element in byteArray)

            {

                checksum += element;

            }

 

            return checksum;

        }

 

        #endregion

    }

}

 

 

TimeoutWebClient.cs

 

 

using System;

using System.Net;

 

namespace DownloadFavicon

{

    /// <summary>

    /// 타임아웃 웹 클라이언트

    /// </summary>

    public class TimeoutWebClient : WebClient

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 타임 아웃

        /// </summary>

        private int timeOut = 5000;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 웹 요청 구하기 - GetWebRequest(uri)

 

        /// <summary>

        /// 웹 요청 구하기

        /// </summary>

        /// <param name="uri">URI</param>

        /// <returns>웹 요청</returns>

        protected override WebRequest GetWebRequest(Uri uri)

        {

            WebRequest webRequest = base.GetWebRequest(uri);

 

            webRequest.Timeout = this.timeOut;

 

            return webRequest;

        }

 

        #endregion

    }

}

 

----------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요