添加ftp支持,支持服务器登录。

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;

namespace prjDownLoad
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(new ThreadStart(Down));
            t.Start();
        }

static void Down()
        {
            DownloadUtil du = new DownloadUtil();
            //订阅事件
            du.DownloadChunkCompleted += new DownloadChunkCompletedHandler(du_DownloadChunkCompleted);
            du.DownloadProgress += new DownloadProgressHandler(du_DownloadProgress);
            du.DownloadCompleted += new DownloadCompletedHandler(du_DownloadCompleted);
            单线程
            byte[] bs = du.DownloadData("ftp://down2.oamo.com:2121/05/31/聚生网管2.10.rar", "www.oamo.com", "www.oamo.com");
            //方法1:使用DownloadData返回的内容。
            FileStream fs = new FileStream("c:\\ee.zip", FileMode.Create, FileAccess.Write);
            fs.Write(bs, 0, bs.Length);
            fs.Flush();
            fs.Close();
        }

/// <summary>
        /// 下载完成事件
        /// </summary>
        static void du_DownloadCompleted(byte[] bs, string extensionFileName)
        {
            //方法2:在下载完成事件中处理。
            FileStream fs = new FileStream("c:\\xx"+extensionFileName, FileMode.Create, FileAccess.Write);
            fs.Write(bs, 0, bs.Length);
            fs.Flush();
            fs.Close();
            Console.WriteLine("全部下载完成。");
        }

/// <summary>
        /// 下载过程事件处理过程
        /// </summary>
        /// <param name="bs"></param>
        static void du_DownloadProgress(DownloadChunk dc)
        {
            Console.WriteLine("线程{0}下载了{1}字节",dc.Number,dc.Content.Length);
        }

/// <summary>
        /// 区块下载完成事件处理过程
        /// </summary>
        static void du_DownloadChunkCompleted(DownloadChunk dc)
        {
            Console.WriteLine("第{0}块下载完成,数据量:{1}",dc.Number,dc.Content.Length);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Text;

namespace prjDownLoad
{
    /// <summary>
    /// 下载的数据块
    /// </summary>
    [Serializable]
    public class DownloadChunk
    {
        //临时存储的集合
        List<byte> content = new List<byte>();

/// <summary>
        /// 整个块的内容
        /// </summary>
        public byte[] Content
        {
            get { return content.ToArray(); }
        }

/// <summary>
        /// 向块中添加内容
        /// </summary>
        /// <param name="bs"></param>
        public void AddContent(byte[] bs)
        {
            content.AddRange(bs);
        }

int from;
        /// <summary>
        /// 开始位置
        /// </summary>
        public int From
        {
            get { return from; }
            set { from = value; }
        }
        int to;
        /// <summary>
        /// 结束位置
        /// </summary>
        public int To
        {
            get { return to; }
            set { to = value; }
        }

int number;
        /// <summary>
        /// 块编号
        /// </summary>
        public int Number
        {
            get { return number; }
            set { number = value; }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace prjDownLoad
{
    /// <summary>
    /// 区块下载完成委托
    /// </summary>
    /// <param name="dc">下载的区块</param>
    public delegate void DownloadChunkCompletedHandler(DownloadChunk dc);
}
using System;
using System.Collections.Generic;
using System.Text;

namespace prjDownLoad
{
    /// <summary>
    /// 下载全部完成委托
    /// </summary>
    /// <param name="bs">完成的byte数组</param>
    /// <param name="extensionFileName">后缀名</param>
    public delegate void DownloadCompletedHandler(byte[] bs,string extensionFileName);
   
}
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;

namespace prjDownLoad
{
    /// <summary>
    /// 下载信息实体类
    /// </summary>
    [Serializable]
    public class DownloadInfo
    {
        DownloadChunk downloadChunk;

public DownloadChunk DownloadChunk
        {
            get { return downloadChunk; }
            set { downloadChunk = value; }
        }

WebRequest webRequest;

/// <summary>
        /// 这个WebRequest中如果是分块下载
        /// 那么在Range中要加上开始和结束位置
        /// </summary>
        public WebRequest WebRequest
        {
            get { return webRequest; }
            set { webRequest = value; }
        }

Stream readStream;
        /// <summary>
        /// 读取数据的流
        /// </summary>
        public Stream ReadStream
        {
            get { return readStream; }
            set { readStream = value; }
        }

byte[] buffer = new byte[1024];
        /// <summary>
        /// 缓冲字节数组,用来存储从流中读取的数据的容器
        /// </summary>
        public byte[] Buffer
        {
            get { return buffer; }
            set { buffer = value; }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace prjDownLoad
{
    /// <summary>
    /// 下载过程委托
    /// </summary>
    /// <param name="dc">下载的区块</param>
    public delegate void DownloadProgressHandler(DownloadChunk dc);
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.IO;

namespace prjDownLoad
{
 public class DownloadUtil
 {
  string userName;
  string passWord;

//开始为1个线程
  int ThreadSum = 1;
  //线程数组
  Thread[] ts;
  DownloadInfo[] dis;
  //已经完成的线程个数
  int completedThreadCount = 0;
  //多线程下载时的容器
  byte[] allChunkContent = new byte[0];

//信号机
  AutoResetEvent autoResetEvent = new AutoResetEvent(false);
  /// <summary>
  /// 区块下载完成事件
  /// </summary>
  public event DownloadChunkCompletedHandler DownloadChunkCompleted;
  /// <summary>
  /// 下载过程事件
  /// </summary>
  public event DownloadProgressHandler DownloadProgress;
  /// <summary>
  /// 某个任务完全下载完成。
  /// </summary>
  public event DownloadCompletedHandler DownloadCompleted;
  //临时保存字节数组的集合(单线程下载时使用)
  List<byte> bytes = new List<byte>();

//扩展名
  string extensionFileName;
  //数据长度
  long length;
  /// <summary>
  /// 下载数据
  /// </summary>
  /// <param name="url">要下载的url</param>
  /// <param name="fileName">要保存的文件名</param>
  /// <returns>下载完成的byte数组</returns>
  public byte[] DownloadData(string url, string userName, string passWord)
  {
   url = System.Web.HttpUtility.UrlDecode(url);
   this.userName = userName;
   this.passWord = passWord;
   length = GetLength(url);
   //每块的大小
   int blockSize = 0;
   //剩下的大小
   int surPlus = 0;

if (length != -1)
   {
    ThreadSum = 5;
    //弄个大小相当的容器
    allChunkContent = new byte[length];
    //每块的大小
    blockSize = (int)(length / ThreadSum);
    //剩下的大小
    surPlus = (int)(length % ThreadSum);
   }

ts = new Thread[ThreadSum];
   dis = new DownloadInfo[ThreadSum];
   //开上几个线程,一块弄
   for (int i = 0; i < ThreadSum; i++)
   {
    //老套路
    WebRequest wr = WebRequest.Create(url);

if (userName != "" && passWord != "")
    {
     wr.Credentials = new NetworkCredential(userName, passWord);
    }

//弄一个DownloadInfo
    dis[i] = new DownloadInfo();
    DownloadInfo di = dis[i];
    //再弄一个DownloadChunk
    DownloadChunk dc = new DownloadChunk();
    di.DownloadChunk = dc;
    //每块的起始位置
    di.DownloadChunk.From = i * blockSize;
    //每块的结束位置(最后一块要加上剩下的大小)
    di.DownloadChunk.To = (int)(i == ThreadSum - 1 ? (i + 1) * blockSize + surPlus : (i + 1) * blockSize);
    //给每个块编号
    di.DownloadChunk.Number = i + 1;
    //向请求中添加获取的范围(Content-Range)
    //如果length为-1,那么意味着,不能用分块的方式下载。
    Uri uri = new Uri(url);
    if (uri.Scheme == Uri.UriSchemeHttp)
    {
     if (length != -1)
     {
      //新玩意:把WebRequest变成HttpWebRequest
      //目的在于向请求头里面添加Content-Range
      HttpWebRequest hwr = (HttpWebRequest)wr;
      hwr.AddRange(di.DownloadChunk.From, di.DownloadChunk.To);
     }
    }
    else
    {
     if (length != -1)
     {
      //新玩意:把WebRequest变成HttpWebRequest
      //目的在于向请求头里面添加Content-Range
      FtpWebRequest hwr = (FtpWebRequest)wr;
      hwr.Method = WebRequestMethods.Ftp.DownloadFile;
      //hwr.AddRange(di.DownloadChunk.From, di.DownloadChunk.To);
     }
    }
    //塞进去
    di.WebRequest = wr;
    //实例化线程
    //ts[i] = new Thread(new ParameterizedThreadStart(DownloadByChunk));
    //也可以考虑将执行的内容加入线程池中。
    ThreadPool.QueueUserWorkItem(new WaitCallback(DownloadByChunk), di);
   }
   如果上面没加入线程池,那么在这里启动线程
   //for (int i = 0; i < ThreadSum; i++)
   //{
   //    ts[i].Start(dis[i]);
   //}
   //还是等着呗
   autoResetEvent.WaitOne();
   return allChunkContent;
  }

public byte[] DownloadData(string url)
  {
   return DownloadData(url, "", "");
  }

/// <summary>
  /// 就是把单线程处理部分的内容抄了一个过来。
  /// </summary>
  /// <param name="obj"></param>
  private void DownloadByChunk(object obj)
  {
   DownloadInfo di = obj as DownloadInfo;
   di.WebRequest.BeginGetResponse(new AsyncCallback(GetResponseCallBackByChunk), di);
  }

/// <summary>
  /// 当有回应对象时调用这个方法来处理(多线程)。
  /// </summary>
  /// <param name="result"></param>
  void GetResponseCallBackByChunk(IAsyncResult result)
  {
   DownloadInfo di = result.AsyncState as DownloadInfo;
   WebRequest wr = di.WebRequest;
   WebResponse wsp = wr.EndGetResponse(result);
   Stream st = wsp.GetResponseStream();

di.ReadStream = st;
   st.BeginRead(di.Buffer, 0, di.Buffer.Length, new AsyncCallback(ReadCallBackByChunk), di);
  }

/// <summary>
  /// 一次读取完成后调用的方法(多线程)
  /// </summary>
  /// <param name="result"></param>
  void ReadCallBackByChunk(IAsyncResult result)
  {
   DownloadInfo di = result.AsyncState as DownloadInfo;
   int x = di.ReadStream.EndRead(result);

if (x > 0)
   {
    byte[] bs = SubBytes(di.Buffer, x);
    //回来的数据先放到块中
    di.DownloadChunk.AddContent(bs);
    if (DownloadProgress != null)
    {
     DownloadProgress(di.DownloadChunk);
    }
    di.ReadStream.BeginRead(di.Buffer, 0, di.Buffer.Length, new AsyncCallback(ReadCallBackByChunk), di);
   }
   else
   {
    di.ReadStream.Close();
    if (DownloadChunkCompleted != null)
    {
     DownloadChunkCompleted(di.DownloadChunk);
    }
    //某个块中的数据全部回来了,再加入容器中
    if (length != -1)
    {
     //如果是多线程
     Array.Copy(di.DownloadChunk.Content, 0, allChunkContent, di.DownloadChunk.From, di.DownloadChunk.Content.Length);
    }
    else
    {
     //如果是单线程。
     allChunkContent = di.DownloadChunk.Content;
    }

//完成的线程计数加一
    completedThreadCount++;
    //如果所有的线程都完了,才发信号,一个线程完了,不发信号

if (completedThreadCount == ThreadSum)
    {
     if (DownloadCompleted != null)
     {
      DownloadCompleted(allChunkContent, extensionFileName);
     }
     autoResetEvent.Set();
    }
   }
  }

/// <summary>
  /// 截取byte数组中的内容
  /// </summary>
  /// <param name="bs">源数组</param>
  /// <param name="length">要截取的长度</param>
  /// <returns>截取的结果数组</returns>
  byte[] SubBytes(byte[] bs, int length)
  {
   byte[] temp = new byte[length];
   Array.Copy(bs, 0, temp, 0, length);
   return temp;
  }

/// <summary>
  /// 获取要下载的数据的长度
  /// 如果为-1,那么不能分块下载
  /// </summary>
  /// <param name="url">要下载的Url</param>
  /// <returns>内容的长度</returns>
  long GetLength(string url)
  {
   url = System.Web.HttpUtility.UrlDecode(url);
   WebRequest wr = WebRequest.Create(url);
   if (userName != "" && passWord != "")
   {
    wr.Credentials = new NetworkCredential(userName, passWord);
   }
   WebResponse wsp = wr.GetResponse();
   Uri uri = new Uri(url);
   long length = wsp.ContentLength;
   string s = wsp.ResponseUri.ToString();
   int pointIndex = s.LastIndexOf(".");
   if (pointIndex != -1)
   {
    extensionFileName = s.Substring(pointIndex);
   }
   else
   {
    extensionFileName = "";
   }
   wr.Abort();
   wsp.Close();
   return length;
  }

}
}

转摘自:http://blog.sina.com.cn/s/blog_49458c270100ipvu.html

转载于:https://www.cnblogs.com/hxworm/articles/1968499.html

[转]数据下载(二十一)相关推荐

  1. 使用redis-shake工具迁移云Redis数据(二十一)

    文章目录 1.在ECS服务器中部署相同版本的Redis 2.安装redis-shake工具 3.redis-shake配置文件 .4.将云Redis数据迁移至ECS的Redis中 5.检查数据的准确率 ...

  2. MODIS数据下载、拼接、转tif

    modis数据的优势在于时间序列长,产品种类多. modis数据下载下来是hdf格式,且一份数据由很多瓦片数据组成,需要进行拼接.投影,转tif等操作 刚开始研究了好久使用MRT来对modis的hdf ...

  3. OSM道路数据下载与处理

    OSM即是OpenStreetMap,是一个志愿者地理信息系统,人们在上面收集数据,下载数据. 文章目录 一.OSM数据的下载 1.OSM的注册 2.选择数据下载 二.OSM数据的转换 三 .数据的解 ...

  4. GISTEMP全球表面温度数据下载及处理

    文章目录 前言 一.数据下载 二.数据处理步骤 1.数据读取 2.计算温度异常变化速率和区域平均值 3.实例展示 总结 前言 GISTEMP全拼为GISS Surface Temperature An ...

  5. android学习(二十一) 下载数据减少电池损耗

    高效的网络访问(优化下载) 使用无线网络下载数据是你的应用消耗电池潜在的重要原因之一.为了降低和网络有关的activity连接导致的电池消耗.你理解你的连接模型怎样影响无线硬件这是很关键的. 下面将介 ...

  6. 某云数据中心网络解决方案(分享二十一)

    某云数据中心网络解决方案(分享二十一) 参考文章: (1)某云数据中心网络解决方案(分享二十一) (2)https://www.cnblogs.com/zywu-king/p/8284189.html ...

  7. FreeSql (二十一)查询返回数据

    FreeSql 采用 ExpressionTree 优化读取速读,如果懂技术的你一定知道 .NETCore 技术下除了原生代码,最快就是 Emit 和 ExpressionTree. 项目在初期使用的 ...

  8. 数据科学和人工智能技术笔记 二十一、统计学

    二十一.统计学 作者:Chris Albon 译者:飞龙 协议:CC BY-NC-SA 4.0 贝塞尔校正 贝塞尔的校正是我们在样本方差和样本标准差的计算中使用 n−1n-1n−1 而不是 nnn 的 ...

  9. 二十一世纪最性感的职业:数据科学家

    性感事物方面的权威<哈佛商业评论>宣布,"数据科学家"是二十一世纪最性感的职业.所谓性感,既代表着难以名状的诱惑,又说明了大家都不知道它干的是什么. 不管老板懂不懂数据 ...

  10. VUE学习(二十一)、Vuex(getters、mapState与mapGetters、mapMutations与mapActions、多组件共享数据、模块化编码)

    VUE学习(二十一).Vuex(getters.mapState与mapGetters.mapMutations与mapActions.多组件共享数据.模块化编码) 一.Vuex普通实现求和案例 演示 ...

最新文章

  1. mysql数据库应用与开发姜桂洪 课后答案_一站式打卡“云原生”时代的高效开发...
  2. arm中断保护和恢复_浅谈ARM处理器的七种异常处理
  3. C和C++结构体区别
  4. django 允许跨域请求
  5. C++编译器默默编写并调用哪些函数
  6. RESTful API 设计思考
  7. keras + tensorflow —— 训练参数数目的计算
  8. python生成wps文件_使用Python操作XLS文件(wps中叫et)
  9. Vagrant:将装在C盘的虚拟机移动到别的目录
  10. 极限学习机和支持向量机_极限学习机的发展
  11. Java 代码生成器(CURD CRUD)
  12. 企业微信工具栏获取外部联系人unionid
  13. 国产操作系统之优麒麟安装
  14. sudo rosdep init 出现 ERROR: cannot download default sources list from:错误解决方法
  15. MySQL查询效率问题
  16. 利用openpyxl在Excel文件中批量复制模板表格
  17. 我在Facebook工作的十大经验分享
  18. 20个免费论文下载入口_含免费知网、万方、维普帐号
  19. mac的angular/cli安装及踩坑记录
  20. ATT加入Verizon与KT的合作圈,共同开发SDN/NFV/5G

热门文章

  1. Idea 打包war文件
  2. 谷歌浏览器如何打开标签时不覆盖原标签
  3. 威联通 QTS5.0 532x :phpmyadmin 安装位置
  4. vue-video-player 更改视频源
  5. 聪明的女人不吸烟不喝酒
  6. 等级保护制度已进入2.0时代,云等保标准颁布在即
  7. 安全世界 5正当时:亚信安全2020第五空间战略发展高峰论坛举行
  8. c语言中一些常用的逻辑运算,C语言中的位运算和逻辑运算
  9. 来!简单了解一下计算机发展史!
  10. 5G+AI+XR:将成为开启空间互联网的钥匙