csharp/7Bytes-Studio/BlackFire/BlackFire/Common/Utility/Utility.Http.cs

Utility.Http.cs
/*
--------------------------------------------------
| Copyright © 2008 Mr-Alan. All rights reserved. |
| Website: www.0x69h.com                         |
| Mail: [email protected]                  |
| QQ: 835988221                                  |
--------------------------------------------------
*/

using System;
using System.Text;
using System.Net;
using System.IO;

namespace BlackFire
{
    public static partial clast Utility
    {
        /// 
        /// Http连接操作帮助类。
        /// 
        public static clast Http
        {
            /// 
            /// HTTP协议的POST方法。
            /// 
            /// POST的目标地址。
            /// 提交的POST数据。
            /// Cookie容器。
            /// 同步返回的服务器响应字符串。
            public static string Post(string Url, string postDataStr, CookieContainer cookieContainer = null)
            {
                cookieContainer = cookieContainer ?? new CookieContainer();
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = Encoding.UTF8.GetByteCount(postDataStr);
                request.CookieContainer = cookieContainer;
                Stream myRequestStream = request.GetRequestStream();
                StreamWriter myStreamWriter = new StreamWriter(myRequestStream, Encoding.GetEncoding("gb2312"));
                myStreamWriter.Write(postDataStr);
                myStreamWriter.Close();

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
                Stream myResponseStream = response.GetResponseStream();
                StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
                string retString = myStreamReader.ReadToEnd();
                myStreamReader.Close();
                myResponseStream.Close();

                return retString;
            }

            /// 
            /// HTTP协议的GET方法。
            /// 
            /// GET的目标地址
            /// 提交的GET数据。
            /// 同步返回的服务器响应字符串。
            public static string Get(string Url, string gettDataStr)
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (gettDataStr == "" ? "" : "?") + gettDataStr);
                request.Method = "GET";
                request.ContentType = "text/html;charset=UTF-8";

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream myResponseStream = response.GetResponseStream();
                StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
                string retString = myStreamReader.ReadToEnd();
                myStreamReader.Close();
                myResponseStream.Close();

                return retString;
            }

            /// 
            /// HTTP协议支持断点续传的文件下载。
            /// 
            /// 下载器必需的参数。
            /// HTTP下载器。
            public static HttpDownloader DownLoad(HttpDownloadInfo httpDownloadInfo)
            {
                var httpDownloader = new HttpDownloader(httpDownloadInfo);
                return httpDownloader;
            }

            #region HttpDownloader

            /// 
            /// HTTP协议支持断点续传的文件下载器。
            /// 
            public sealed clast HttpDownloader
            {
                private HttpDownloadInfo m_HttpDownloadInfo;
                private long m_Position;
                private FileStream m_FileStream;
                private bool m_Hasttop;

                public event EventHandler OnDownloadSuccess;
                public event EventHandler OnDownloadFailure;
                public event EventHandler OnDownloadProgress;

                /// 
                /// 构造方法。
                /// 
                /// HTTP下载信息。
                internal HttpDownloader(HttpDownloadInfo httpDownloadInfo)
                {
                    m_HttpDownloadInfo = httpDownloadInfo;
                    DownloadFileCheck();
                }

                /// 
                /// 开启下载。
                /// 
                public void StartDownload()
                {
                    try
                    {
                        HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(m_HttpDownloadInfo.Url);

                        if (0L < m_Position)
                        {
                            httpWebRequest.AddRange((int)m_Position);
                        }

                        WebResponse webResponse = httpWebRequest.GetResponse();
                        Stream webResponseStream = webResponse.GetResponseStream();

                        float progress = 0f;
                        long currentSize = m_Position;
                        long totalSize = m_Position + webResponse.ContentLength;

                        byte[] btContent = new byte[m_HttpDownloadInfo.DownloadBufferUnit];
                        int readSize = 0;
                        while (!m_Hasttop && 0 < (readSize = webResponseStream.Read(btContent, 0, m_HttpDownloadInfo.DownloadBufferUnit)))
                        {
                            progress = (float)(currentSize += readSize) / totalSize;
                            if (null != OnDownloadProgress)
                            {
                                OnDownloadProgress.Invoke(this, new HttpDownloaderProgressEventArgs(progress));
                            }
                            m_FileStream.Flush();
                            m_FileStream.Write(btContent, 0, readSize);

                            System.Threading.Thread.Sleep(10);

                        }
                        m_FileStream.Close();
                        webResponseStream.Close();

                        if (!m_Hasttop)
                        {
                            ReNameTempFile();

                            if (null != OnDownloadSuccess)
                            {
                                OnDownloadSuccess.Invoke(this, EventArgs.Empty);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if (null != OnDownloadFailure)
                        {
                            OnDownloadFailure.Invoke(this,new HttpDownloaderFailureEventArgs(ex));
                        }
                        throw ex;
                    }
                }

                /// 
                /// 停止下载。
                /// 
                public void StopDownload()
                {
                    m_Hasttop = true;
                }

                private void DownloadFileCheck()
                {
                    var tmpFileName = m_HttpDownloadInfo.SavePath +"."+ m_HttpDownloadInfo.TempFileExtension;
                    if (File.Exists(tmpFileName))
                    {
                        m_FileStream = File.OpenWrite(tmpFileName);
                        m_Position = m_FileStream.Length;
                        m_FileStream.Seek(m_Position, SeekOrigin.Current);
                    }
                    else
                    {
                        m_FileStream = new FileStream(tmpFileName, FileMode.Create);
                        m_Position = 0L;
                    }
                }

                private void ReNameTempFile()
                {
                    if (File.Exists(m_HttpDownloadInfo.SavePath + "." + m_HttpDownloadInfo.TempFileExtension))
                    {
                        if (File.Exists(m_HttpDownloadInfo.SavePath))
                        {
                            File.Delete(m_HttpDownloadInfo.SavePath);
                        }

                        FileInfo fileInfo = new FileInfo(m_HttpDownloadInfo.SavePath + "." + m_HttpDownloadInfo.TempFileExtension);
                        fileInfo.MoveTo(m_HttpDownloadInfo.SavePath);
                        //File.Move(m_HttpDownloadInfo.SavePath + m_HttpDownloadInfo.TempFileExtension, m_HttpDownloadInfo.SavePath);
                    }
                }

            }

            /// 
            /// HTTP下载信息。
            /// 
            public clast HttpDownloadInfo
            {
                /// 
                /// 构造方法。
                /// 
                /// 下载地址。
                /// 下载下来的文件保存的路径。
                /// 下载过程中临时保存的文件扩展名。
                /// 下载处理的缓冲区,一般与带宽有关。
                /// 下载成功的回调。
                /// 下载失败的回调。
                /// 下载过程的回调。
                public HttpDownloadInfo(string url, string savePath, string tempFileExtension, int downloadBufferUnit, EventHandler onDownloadSuccess, EventHandler onDownloadFailure, EventHandler onDownloadProgress)
                {
                    Url = url;
                    SavePath = savePath;
                    TempFileExtension = tempFileExtension;
                    DownloadBufferUnit = downloadBufferUnit;
                    OnDownloadSuccess = onDownloadSuccess;
                    OnDownloadFailure = onDownloadFailure;
                    OnDownloadProgress = onDownloadProgress;
                }


                internal string Url;
                internal string SavePath;
                internal string TempFileExtension;
                internal int DownloadBufferUnit = 512;
                internal EventHandler OnDownloadSuccess;
                internal EventHandler OnDownloadFailure;
                internal EventHandler OnDownloadProgress;
            }

            /// 
            /// HTTP下载器的Progress事件参数。
            /// 
            public sealed clast HttpDownloaderProgressEventArgs : EventArgs
            {
                public HttpDownloaderProgressEventArgs(float progress)
                {
                    DownloadProgress = progress;
                }

                public float DownloadProgress { get; private set; }
            }

            /// 
            /// HTTP下载器的Failure事件参数。
            /// 
            public sealed clast HttpDownloaderFailureEventArgs : EventArgs
            {
                public HttpDownloaderFailureEventArgs(Exception ex)
                {
                    Exception = ex;
                }

                public Exception Exception { get; private set; }
            }

            #endregion



            public static HttpServer CreateHttpServer(HttpServerInfo httpServerInfo)
            {
                var httpServer = new HttpServer(httpServerInfo);
                return httpServer;
            }


            #region HTTP Server

            public clast HttpServerInfo
            {
                public string Ip;
                public int Port;

                public string[] Prefixes;

                public EventHandler OnStartSucceed;
                public EventHandler OnStartFailure;

                public Func GetHandler;
                public Func PostHandler;
                public Func DefaultHandler;

                public Action OnBeforeResponse;
            }

            public sealed clast StartFailureEventArgs : EventArgs
            {
                public StartFailureEventArgs(Exception exception)
                {
                    Exception = exception;
                }

                public Exception Exception { get; private set; }

            }

            public clast LazyHttpServerInfo : HttpServerInfo
            {

                public LazyHttpServerInfo(Func getLazyHandler, Func postLazyHandler, Func defaultLazyHandler)
                {


                    GetLazyHandler = getLazyHandler;
                    PostLazyHandler = postLazyHandler;
                    DefaultLazyHandler = defaultLazyHandler;


                    GetHandler = request => {
                        var handlerContent = string.Empty;
                        if (null!= GetLazyHandler)
                        {
                            handlerContent = GetLazyHandler.Invoke(request.RawUrl);
                        }
                        return Encoding.UTF8.GetBytes(handlerContent);
                    };

                    PostHandler = request => {
                        var handlerContent = string.Empty;
                        if (null != PostLazyHandler)
                        {
                            using (StreamReader getPostParam = new StreamReader(request.InputStream, true))
                            {
                                var postData = getPostParam.ReadToEnd();
                                handlerContent = PostLazyHandler.Invoke(postData);
                            }
                        }
                        return Encoding.UTF8.GetBytes(handlerContent);
                    };

                    DefaultHandler = request => {
                        var handlerContent = string.Empty;
                        if (null != DefaultLazyHandler)
                        {
                            handlerContent = DefaultLazyHandler.Invoke(request.RawUrl);
                        }
                        return Encoding.UTF8.GetBytes(handlerContent);
                    };




                }

                public Func GetLazyHandler;
                public Func PostLazyHandler;
                public Func DefaultLazyHandler;
            }



            public clast HttpServer
            {
                private HttpServerInfo m_HttpServerInfo = null;

                public bool IsWorking { get; private set; }

                public string Ip { get; private set; }
                public int Port { get; private set; }

                public string Address { get; private set; }



                public string[] Prefixes { get; private set; }


                /// 
                /// 监听器
                /// 
                private HttpListener m_HttpListener;


                public HttpServer(HttpServerInfo httpServerInfo)
                {
                    if (null== httpServerInfo)
                    {
                        throw new ArgumentNullException(string.Format("构造方法的参数:{0}不能为空。", "httpServerInfo"));
                    }
                    m_HttpServerInfo = httpServerInfo;
                    Ip = httpServerInfo.Ip;
                    Port = httpServerInfo.Port;
                    Address = string.Format("{0}:{1}", @"http://"+ Ip, Port);
                    Prefixes = httpServerInfo.Prefixes;
                }


                public void Start()
                {
                    if (IsWorking) return;

                    try
                    {
                        m_HttpListener = new HttpListener();
                        //监听的路径
                        m_HttpListener.Prefixes.Add(Address + "/");
                        for (int i = 0; i < Prefixes.Length; i++)
                        {
                            m_HttpListener.Prefixes.Add(Prefixes[i]);
                        }
                        //设置匿名访问
                        m_HttpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                        m_HttpListener.Start();

                        if (null != m_HttpServerInfo.OnStartSucceed)
                        {
                            m_HttpServerInfo.OnStartSucceed.Invoke(this, EventArgs.Empty);
                        }

                        IsWorking = true;



                        while (IsWorking)
                        {
                            var context = m_HttpListener.GetContext();
                            HttpListenerRequest request = context.Request;
                            HttpListenerResponse response = context.Response;
                            response.ContentEncoding = Encoding.UTF8;
                            response.AddHeader("Access-Control-Allow-Origin", "*"); //允许跨域请求。

                            byte[] handleContent = null;
                            if (request.HttpMethod == "GET")
                            {
                                if (null != m_HttpServerInfo.GetHandler)
                                {
                                    handleContent = m_HttpServerInfo.GetHandler.Invoke(request);
                                }

                            }
                            else if (request.HttpMethod == "POST")
                            {
                                if (null != m_HttpServerInfo.PostHandler)
                                {
                                    handleContent = m_HttpServerInfo.PostHandler.Invoke(request);
                                }
                            }
                            else
                            {
                                if (null != m_HttpServerInfo.DefaultHandler)
                                {
                                    handleContent = m_HttpServerInfo.DefaultHandler.Invoke(request);
                                }
                            }

                            if (null!= m_HttpServerInfo.OnBeforeResponse)
                            {
                                m_HttpServerInfo.OnBeforeResponse.Invoke(response);
                            }

                            response.ContentLength64 = handleContent.Length;
                            Stream output = response.OutputStream;
                            output.Write(handleContent, 0, handleContent.Length);
                            output.Close();
                        }

                        m_HttpListener.Close();
                        m_HttpListener.Abort();
                    }
                    catch (Exception ex)
                    {
                        IsWorking = false;
                        if (null != m_HttpServerInfo.OnStartFailure)
                        {
                            m_HttpServerInfo.OnStartFailure.Invoke(this,new StartFailureEventArgs(ex));
                        }
                    }








                }

                public void Close()
                {
                    IsWorking = false;
                }

            }


            #endregion



        }

    }
}