http多线程下载

 

using  System;
using  System.IO;
using  System.Net;
using  System.Text;
using  System.Security;
using  System.Threading;
using  System.Collections.Specialized;
using  System.Diagnostics;
using  System.Data;

namespace  HttpDownload.DownloadFile
{
    
/// <summary>
    
/// Download file info
    
/// </summary>

    [Serializable()]
    
public class DownloadFileInfo
    
{
        
private string _requestURL;
        
private string _responseURL;
        
private string _fileName;
        
private int _totalSize;
        
private int _blockLeftSize;

        
public string RequestURL
        
{
            
get return _requestURL; }
        }


        
public string ResponseURL
        
{
            
get return _responseURL; }
        }


        
public string FileName
        
{
            
get return _fileName; }
        }


        
public int TotalSize
        
{
            
get return _totalSize; }
            
set { _totalSize = value; }
        }


        
public int BlockLeftSize
        
{
            
get return _blockLeftSize; }
            
set { _blockLeftSize = value; }
        }


        
public DownloadFileInfo(string requestURL, string responseURL, string fileName, int totalSize, int blockLeftSize)
        
{
            
this._requestURL = requestURL;
            
this._responseURL = responseURL;
            
this._fileName = fileName;
            
this._totalSize = totalSize;
            
this._blockLeftSize = blockLeftSize;
        }


        
public DownloadFileInfo(string requestURL, string responseURL, string fileName)
            : 
this(requestURL, responseURL, fileName, 00)
        
{
        }


        
public DownloadFileInfo(string url, string fileName)
            : 
this(url, url, fileName, 00)
        
{
        }


        
private DownloadFileInfo()
        
{
        }


        
public static DownloadFileInfo CreatFileInfo(DataRow drFileInfo)
        
{
            DownloadFileInfo newFileInfo 
= new DownloadFileInfo();
            newFileInfo._requestURL 
= drFileInfo["RequestURL"].ToString();
            newFileInfo._responseURL 
= drFileInfo["ResponseURL"].ToString();
            newFileInfo._fileName 
= drFileInfo["FileName"].ToString();
            newFileInfo._totalSize 
= Convert.ToInt32(drFileInfo["TotalSize"].ToString());
            newFileInfo._blockLeftSize 
= Convert.ToInt32(drFileInfo["BlockLeftSize"].ToString());
            
return newFileInfo;
        }

    }


    
/// <summary>
    
/// Download event arguments
    
/// </summary>

    public class DownLoadEventArgs : System.EventArgs
    
{
        
private DownloadFileInfo _downloadFileInfo;
        
private int _position;
        
private int _readCount;
        
private int _threadNO;

        
public DownloadFileInfo DownFileInfo
        
{
            
get return _downloadFileInfo; }
        }


        
public int StartPosition
        
{
            
get return _position; }
        }


        
public int ReadCount
        
{
            
get return _readCount; }
        }


        
public int ThreadNO
        
{
            
get return _threadNO; }
        }


        
public DownLoadEventArgs(DownloadFileInfo DownFileInfo, int nStartPostion, int nReadCount, int nThreadNO)
        
{
            
this._downloadFileInfo = DownFileInfo;
            
this._position = nStartPostion;
            
this._readCount = nReadCount;
            
this._threadNO = nThreadNO;
        }

    }


    
/// <summary>
    
/// class for sub-download threads
    
/// </summary>

    public class SubDownloadThread
    
{
        
private int _threadNO;
        
private int _position;
        
private int _blockSizeLeft;
        
private bool _isStopped;
        
private Thread thdDownload;
        
const int BUFFER_SIZE = 0x10000;//64k buffer size
        private readonly DownloadFileInfo _fileInfo;
        
private EventHandler _finished;
        
public event EventHandler<DownLoadEventArgs> DataReceived;

        
public SubDownloadThread(DownloadFileInfo DownFileInfo, int ThreadNO, int Position, int BlockSizeLeft, EventHandler Finished)
        
{
            
this._fileInfo = DownFileInfo;
            
this._threadNO = ThreadNO;
            
this._position = Position;
            
this._blockSizeLeft = BlockSizeLeft;
            
this._finished = Finished;
        }


        
/// <summary>
        
/// Start to create thread to download file
        
/// </summary>


        
public void StartDownload()
        
{
            thdDownload 
= new Thread(new ThreadStart(this.Download));
            thdDownload.Start();
        }


        
/// <summary>
        
/// Stop current download-thread
        
/// </summary>

        public void Stop()
        
{
            _isStopped 
= true;
            
if (thdDownload.ThreadState == System.Threading.ThreadState.Running)
            
{
                thdDownload.Join(
10);
            }

            Debug.WriteLine(
string.Format("Thread NO:{0} is stopped!", _threadNO));
        }


        
/// <summary>
        
/// Function for sub-thread
        
/// </summary>

        private void Download()
        
{
            HttpWebResponse hwrp 
= null;
            
try
            
{
                Debug.WriteLine(
string.Format("Thread NO:{0} begins to download!", _threadNO));
                
// Creat request by url 
                HttpWebRequest hwrq = (HttpWebRequest)WebRequest.Create(new Uri(this._fileInfo.RequestURL));
                
// Go to download position
                hwrq.AddRange(_position);
                
// Get response from request
                hwrp = (HttpWebResponse)hwrq.GetResponse();
            }

            
catch (Exception e)
            
{
                Debug.WriteLine(e.Message);
                
return;
            }

            
// download and write data from 
            Debug.WriteLine(string.Format("Thread NO:{0} call function named DownloadData!", _threadNO));
            DownloadData(hwrp);
            hwrp.Close();
//Close response here
        }


        
/// <summary>
        
/// Download data through web request
        
/// </summary>
        
/// <param name="Response"></param>

        private void DownloadData(WebResponse Response)
        
{
            
byte[] bBuffer = new byte[BUFFER_SIZE];

            Stream sReader 
= Response.GetResponseStream();
            
if (sReader == nullreturn;
            
int nReadCount = 0;

            
while (!_isStopped && this._blockSizeLeft > 0)
            
{
                Debug.WriteLine(
string.Format("Thread NO:{0} reads data!", _threadNO));
                
// Set read size
                nReadCount = (BUFFER_SIZE > this._blockSizeLeft) ? this._blockSizeLeft : BUFFER_SIZE;//Get current read count

                
// Read data
                int nRealReadCount = sReader.Read(bBuffer, 0, nReadCount);
                
if (nRealReadCount <= 0break;
                Debug.WriteLine(
string.Format("Thread NO:{0} writes data!", _threadNO));
                
// Write data
                using (FileStream sw = new FileStream(this._fileInfo.FileName + DownloadThread.filenameExt, 
                    System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite))
                
{
                    sw.Position 
= this._position;
                    sw.Write(bBuffer, 
0, nRealReadCount);
                    Debug.WriteLine(
string.Format("Thread NO:{0} writes {1} data!", _threadNO, nRealReadCount));
                    sw.Flush();
                    sw.Close();
                }


                Debug.WriteLine(
string.Format("Thread NO:{0} send callback info!", _threadNO));

                
// Call back
                EventHandler<DownLoadEventArgs> receivedHandler = DataReceived;
                
if (receivedHandler != null)
                
{
                    receivedHandler(
this,new DownLoadEventArgs(
                        
this._fileInfo, this._position, nRealReadCount, this._threadNO));
                }


                
// Set position and block left 
                this._position += nRealReadCount;
                
this._blockSizeLeft -= nRealReadCount;
            }


            
if (_isStopped)
            
{
                
return;
            }

            Debug.WriteLine(
string.Format("Thread NO:{0} sends finish-info!", _threadNO));
            EventHandler finishHandle 
= _finished;
            
if (finishHandle != null)
            
{
                finishHandle(
this,EventArgs.Empty);
            }

        }

    }


    
/// <summary>
    
/// Class for download thread
    
/// </summary>

    public class DownloadThread
    
{
        
private DownloadFileInfo _fileInfo;
        
private SubDownloadThread[] subThreads;
        
private int nThreadFinishedCount;
        
private DataRow drFileInfo;
        
private DataTable dtThreadInfo;
        
public EventHandler<DownLoadEventArgs> DataReceived;
        
public event EventHandler Finished;
        
public  const string filenameExt = ".bf!";      //未下载完的扩展名

        
public DataTable ThreadInfo
        
{
            
get return dtThreadInfo; }
        }


        
/// Class's Constructor
        public DownloadThread(string requestURL, string responseURL, string fileName, DataRow newFileInfo, int subThreadNum)
        
{
            
// Create download file info
            _fileInfo = new DownloadFileInfo(requestURL, responseURL, fileName);
            
// Create request to get file info
            bool blnMultiDownload = GetFileDownInfo();

            
// Create file info datarow
            drFileInfo = newFileInfo;
            InitDataRow();
            
// Create subthreads and set these info in threadinfo table
            if (subThreadNum <= 0) subThreadNum = 5;//Defualt value
            
//Not support to be multi-thread download or less than 64k
            if (!blnMultiDownload || _fileInfo.TotalSize <= 0x10000) subThreadNum = 1;
            subThreads 
= new SubDownloadThread[subThreadNum];
            nThreadFinishedCount 
= 0;
            CreateThreadTable(subThreadNum);
        }


        
public DownloadThread(string url, string fileName)
            : 
this(url, url, fileName, null2)
        
{
        }


        
public DownloadThread(DataRow downloadFileInfo, DataTable threadInfos)
        
{
            
// Create download file info
            drFileInfo = downloadFileInfo;
            _fileInfo 
= new DownloadFileInfo(drFileInfo["RequestURL"].ToString(),
                drFileInfo[
"ResponseURL"].ToString(),
                drFileInfo[
"FileName"].ToString(),
                Convert.ToInt32(drFileInfo[
"TotalSize"].ToString()),
                Convert.ToInt32(drFileInfo[
"BlockLeftSize"].ToString()));
            
// Create sub thread class objects
            dtThreadInfo = threadInfos;
            subThreads 
= new SubDownloadThread[dtThreadInfo.Rows.Count];
            nThreadFinishedCount 
= 0;
        }


        
/// {Class's Constructor}
        
/// <summary>
        
/// Start to download
        
/// </summary>

        public void Start()
        
{
            StartSubThreads();
        }


        
/// <summary>
        
/// Create table to save thread info 
        
/// </summary>
        
/// <param name="SubThreadNum"></param>

        private void CreateThreadTable(int SubThreadNum)
        
{
            
int nThunkSize = _fileInfo.TotalSize / SubThreadNum;
            dtThreadInfo 
= new DataTable("DownloadFileInfo");
            dtThreadInfo.Columns.Add(
"ThreadNO"typeof(int));
            dtThreadInfo.Columns.Add(
"Position"typeof(int));
            dtThreadInfo.Columns.Add(
"BlockLeftSize"typeof(int));

            DataRow drNew;
            
int i = 0;
            
for (; i < SubThreadNum - 1; i++)
            
{
                drNew 
= dtThreadInfo.NewRow();
                drNew[
"ThreadNO"= i;
                drNew[
"Position"= i * nThunkSize;
                drNew[
"BlockLeftSize"= nThunkSize;
                dtThreadInfo.Rows.Add(drNew);
            }


            drNew 
= dtThreadInfo.NewRow();
            drNew[
"ThreadNO"= i;
            drNew[
"Position"= i * nThunkSize;
            drNew[
"BlockLeftSize"= _fileInfo.TotalSize - i * nThunkSize;
            dtThreadInfo.Rows.Add(drNew);
            dtThreadInfo.AcceptChanges();
        }


        
/// <summary>
        
/// Start sub-threads to download file
        
/// </summary>

        private void StartSubThreads()
        
{
            
foreach (DataRow dr in dtThreadInfo.Rows)
            
{
                
int ThreadNO = Convert.ToInt32(dr["ThreadNO"].ToString());
                
if (Convert.ToInt32(dr["BlockLeftSize"].ToString()) > 0)
                
{
                    subThreads[ThreadNO] 
= new SubDownloadThread(_fileInfo, ThreadNO,
                        Convert.ToInt32(dr[
"Position"].ToString()),
                        Convert.ToInt32(dr[
"BlockLeftSize"].ToString()),
                        
new EventHandler(this.DownloadFinished));
                    subThreads[ThreadNO].DataReceived 
+= this.DataReceived;
                    subThreads[ThreadNO].StartDownload();
                }

                
else
                
{
                    DownloadFinished(
this,EventArgs.Empty);
                }

            }

        }


        
/// <summary>
        
/// Save download file info
        
/// </summary>

        private void InitDataRow()
        
{
            
if (drFileInfo != null)
            
{
                drFileInfo.BeginEdit();
                drFileInfo[
"RequestURL"= _fileInfo.RequestURL;
                drFileInfo[
"ResponseURL"= _fileInfo.ResponseURL;
                drFileInfo[
"FileName"= _fileInfo.FileName;
                drFileInfo[
"TotalSize"= _fileInfo.TotalSize;
                drFileInfo[
"BlockLeftSize"= _fileInfo.BlockLeftSize;
                drFileInfo[
"CreatedTime"= DateTime.Now.ToString("yyyyMMddHHmmss");
                drFileInfo.EndEdit();
                drFileInfo.AcceptChanges();
            }

        }


        
/// <summary>
        
/// Check url to get download file info
        
/// </summary>
        
/// <returns></returns>

        private bool GetFileDownInfo()
        
{
            HttpWebRequest hwrq;
            HttpWebResponse hwrp 
= null;
            
try
            
{
                
//Create request
                hwrq = (HttpWebRequest)WebRequest.Create(_fileInfo.RequestURL);
                hwrp 
= (HttpWebResponse)hwrq.GetResponse();
                
//Get file size info
                long L = hwrp.ContentLength;
                L 
= ((L == -1|| (L > 0x7fffffff)) ? ((long)0x7fffffff) : L;

                _fileInfo.TotalSize 
= (int)L;
                _fileInfo.BlockLeftSize 
= _fileInfo.TotalSize;

                
//Check whether this url is supported to be multi-threads download
                bool blnMulti = (hwrp.Headers["Accept-Ranges"!= null && hwrp.Headers["Accept-Ranges"== "bytes");
                hwrp.Close();
//Close response here
                return blnMulti;
            }

            
catch (Exception e)
            
{
                
throw e;
            }

        }


        
/// <summary>
        
/// Update download thread info
        
/// </summary>
        
/// <param name="ThreadNO"></param>
        
/// <param name="Position"></param>
        
/// <param name="DownloadSize"></param>

        public void UpdateDownloadInfo(int ThreadNO, int Position, int DownloadSize)
        
{
            
if (ThreadNO >= dtThreadInfo.Rows.Count)
            
{
                
return;
            }

            DataRow drThreadNO 
= dtThreadInfo.Rows[ThreadNO];
            drThreadNO[
"Position"= Position + DownloadSize;
            drThreadNO[
"BlockLeftSize"= Convert.ToInt32(drThreadNO["BlockLeftSize"].ToString())
                
- DownloadSize;
            drThreadNO.AcceptChanges();

            drFileInfo[
"BlockLeftSize"= Convert.ToInt32(drFileInfo["BlockLeftSize"].ToString()) - DownloadSize;
        }


        
/// <summary>
        
/// Stop download threads
        
/// </summary>

        public void Stop()
        
{
            
for (int i = 0; i < subThreads.Length; i++)
            
{
                subThreads[i].Stop();
            }

        }


        
/// <summary>
        
/// Thread download finished
        
/// </summary>

        private void DownloadFinished(object sender,EventArgs e)
        
{
            
// Some download thread finished
            nThreadFinishedCount++;
            
if (nThreadFinishedCount == subThreads.Length)
            
{
                
// All download threads finished
                if (drFileInfo != null)
                
{
                    drFileInfo.Delete();
                    drFileInfo.AcceptChanges();
                }


                File.Move(_fileInfo.FileName 
+ filenameExt, GetNewFilename(_fileInfo.FileName));

                EventHandler handler 
= Finished;
                
if (handler != null)
                
{
                    handler(
this,EventArgs.Empty);
                }

            }

        }

        
/// <summary>
        
/// 得到新名称
        
/// </summary>
        
/// <returns></returns>

        public static string GetNewFilename(string filename)
        
{
            
if (File.Exists(filename))
            
{
                
string newname = filename;
                
int i = 0;
                
int lastPoint = filename.LastIndexOf('.');
                
do
                
{
                    i
++;
                    
if (lastPoint < 1)
                    
{
                        newname 
= filename + "(" + i + ")";
                    }

                    
else
                    
{
                        newname 
= filename.Substring(0, lastPoint) + "(" + i + ")" + filename.Substring(lastPoint);
                    }

                }

                
while (File.Exists(newname));
                
return newname;
            }

            
else
            
{
                
return filename;
            }

        }

    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值