码迷,mamicode.com
首页 > Windows程序 > 详细

c#上传下载ftp(支持断点续传)

时间:2016-06-20 23:49:15      阅读:707      评论:0      收藏:0      [点我收藏+]

标签:

 

 

技术分享using System;
技术分享using System.Net;
技术分享using System.IO;
技术分享using System.Text;
技术分享using System.Net.Sockets;
技术分享
技术分享namespace ftpGet
技术分享{
技术分享    /// <summary>
技术分享    /// FTP Client
技术分享    /// </summary>
技术分享    public class FTPClient
技术分享    {
技术分享        构造函数
技术分享
技术分享        登陆字段、属性
技术分享
技术分享        链接
技术分享
技术分享        传输模式
技术分享
技术分享        文件操作
技术分享
技术分享        #region 上传和下载
技术分享        /// <summary>
技术分享        /// 下载一批文件
技术分享        /// </summary>
技术分享        /// <param name="strFileNameMask">文件名的匹配字符串</param>
技术分享        /// <param name="strFolder">本地目录(不得以\结束)</param>
技术分享        public void Get(string strFileNameMask, string strFolder)
技术分享        {
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            string[] strFiles = Dir(strFileNameMask);
技术分享            foreach (string strFile in strFiles)
技术分享            {
技术分享                if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
技术分享                {
技术分享                    if (strFile.LastIndexOf(".") > -1)
技术分享                    {
技术分享                        Get(strFile.Replace("\r", ""), strFolder, strFile.Replace("\r", ""));
技术分享                    }
技术分享                }
技术分享            }
技术分享        }
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 下载目录
技术分享        /// </summary>
技术分享        /// <param name="strRemoteFileName">要下载的文件名</param>
技术分享        /// <param name="strFolder">本地目录(不得以\结束)</param>
技术分享        /// <param name="strLocalFileName">保存在本地时的文件名</param>
技术分享        public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)
技术分享        {
技术分享            if (strLocalFileName.StartsWith("-r"))
技术分享            {
技术分享                string[] infos = strLocalFileName.Split(‘ ‘);
技术分享                strRemoteFileName=strLocalFileName = infos[infos.Length - 1];
技术分享
技术分享                if (!bConnected)
技术分享                {
技术分享                    Connect();
技术分享                }
技术分享                SetTransferType(TransferType.Binary);
技术分享                if (strLocalFileName.Equals(""))
技术分享                {
技术分享                    strLocalFileName = strRemoteFileName;
技术分享                }
技术分享                if (!File.Exists(strLocalFileName))
技术分享                {
技术分享                    Stream st = File.Create(strLocalFileName);
技术分享                    st.Close();
技术分享                }
技术分享
技术分享                FileStream output = new
技术分享                    FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
技术分享                Socket socketData = CreateDataSocket();
技术分享                SendCommand("RETR " + strRemoteFileName);
技术分享                if (!(iReplyCode == 150 || iReplyCode == 125
技术分享                || iReplyCode == 226 || iReplyCode == 250))
技术分享                {
技术分享                    throw new IOException(strReply.Substring(4));
技术分享                }
技术分享                while (true)
技术分享                {
技术分享                    int iBytes = socketData.Receive(buffer, buffer.Length, 0);
技术分享                    output.Write(buffer, 0, iBytes);
技术分享                    if (iBytes <= 0)
技术分享                    {
技术分享                        break;
技术分享                    }
技术分享                }
技术分享                output.Close();
技术分享                if (socketData.Connected)
技术分享                {
技术分享                    socketData.Close();
技术分享                }
技术分享                if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享                {
技术分享                    ReadReply();
技术分享                    if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享                    {
技术分享                        throw new IOException(strReply.Substring(4));
技术分享                    }
技术分享                }
技术分享            }
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 下载一个文件
技术分享        /// </summary>
技术分享        /// <param name="strRemoteFileName">要下载的文件名</param>
技术分享        /// <param name="strFolder">本地目录(不得以\结束)</param>
技术分享        /// <param name="strLocalFileName">保存在本地时的文件名</param>
技术分享        public void GetFile(string strRemoteFileName, string strFolder, string strLocalFileName)
技术分享        {
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            SetTransferType(TransferType.Binary);
技术分享            if (strLocalFileName.Equals(""))
技术分享            {
技术分享                strLocalFileName = strRemoteFileName;
技术分享            }
技术分享            if (!File.Exists(strLocalFileName))
技术分享            {
技术分享                Stream st = File.Create(strLocalFileName);
技术分享                st.Close();
技术分享            }
技术分享
技术分享            FileStream output = new
技术分享                FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
技术分享            Socket socketData = CreateDataSocket();
技术分享            SendCommand("RETR " + strRemoteFileName);
技术分享            if (!(iReplyCode == 150 || iReplyCode == 125
技术分享            || iReplyCode == 226 || iReplyCode == 250))
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享            while (true)
技术分享            {
技术分享                int iBytes = socketData.Receive(buffer, buffer.Length, 0);
技术分享                output.Write(buffer, 0, iBytes);
技术分享                if (iBytes <= 0)
技术分享                {
技术分享                    break;
技术分享                }
技术分享            }
技术分享            output.Close();
技术分享            if (socketData.Connected)
技术分享            {
技术分享                socketData.Close();
技术分享            }
技术分享            if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享            {
技术分享                ReadReply();
技术分享                if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享                {
技术分享                    throw new IOException(strReply.Substring(4));
技术分享                }
技术分享            }
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 下载一个文件
技术分享        /// </summary>
技术分享        /// <param name="strRemoteFileName">要下载的文件名</param>
技术分享        /// <param name="strFolder">本地目录(不得以\结束)</param>
技术分享        /// <param name="strLocalFileName">保存在本地时的文件名</param>
技术分享        public void GetBrokenFile(string strRemoteFileName, string strFolder, string strLocalFileName,long size)
技术分享        {
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            SetTransferType(TransferType.Binary);
技术分享
技术分享            
技术分享
技术分享            FileStream output = new
技术分享                FileStream(strFolder + "\\" + strLocalFileName, FileMode.Append);
技术分享            Socket socketData = CreateDataSocket();
技术分享            SendCommand("REST " + size.ToString());
技术分享            SendCommand("RETR " + strRemoteFileName);
技术分享            if (!(iReplyCode == 150 || iReplyCode == 125
技术分享            || iReplyCode == 226 || iReplyCode == 250))
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享
技术分享            //int byteYu = (int)size % 512;
技术分享            //int byteChu = (int)size / 512;
技术分享            //byte[] tempBuffer = new byte[byteYu];
技术分享            //for (int i = 0; i < byteChu; i++)
技术分享            //{
技术分享            //    socketData.Receive(buffer, buffer.Length, 0);
技术分享            //}
技术分享    
技术分享            //socketData.Receive(tempBuffer, tempBuffer.Length, 0);
技术分享
技术分享            //socketData.Receive(buffer, byteYu, 0);
技术分享            while (true)
技术分享            {
技术分享                int iBytes = socketData.Receive(buffer, buffer.Length, 0);
技术分享                //totalBytes += iBytes;
技术分享                
技术分享                output.Write(buffer, 0, iBytes);
技术分享                if (iBytes <= 0)
技术分享                {
技术分享                    break;
技术分享                }
技术分享            }
技术分享            output.Close();
技术分享            if (socketData.Connected)
技术分享            {
技术分享                socketData.Close();
技术分享            }
技术分享            if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享            {
技术分享                ReadReply();
技术分享                if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享                {
技术分享                    throw new IOException(strReply.Substring(4));
技术分享                }
技术分享            }
技术分享        }
技术分享
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 上传一批文件
技术分享        /// </summary>
技术分享        /// <param name="strFolder">本地目录(不得以\结束)</param>
技术分享        /// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
技术分享        public void Put(string strFolder, string strFileNameMask)
技术分享        {
技术分享            string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask);
技术分享            foreach (string strFile in strFiles)
技术分享            {
技术分享                //strFile是完整的文件名(包含路径)
技术分享                Put(strFile);
技术分享            }
技术分享        }
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 上传一个文件
技术分享        /// </summary>
技术分享        /// <param name="strFileName">本地文件名</param>
技术分享        public void Put(string strFileName)
技术分享        {
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            Socket socketData = CreateDataSocket();
技术分享            SendCommand("STOR " + Path.GetFileName(strFileName));
技术分享            if (!(iReplyCode == 125 || iReplyCode == 150))
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享            FileStream input = new
技术分享            FileStream(strFileName, FileMode.Open);
技术分享            int iBytes = 0;
技术分享            while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
技术分享            {
技术分享                socketData.Send(buffer, iBytes, 0);
技术分享            }
技术分享            input.Close();
技术分享            if (socketData.Connected)
技术分享            {
技术分享                socketData.Close();
技术分享            }
技术分享            if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享            {
技术分享                ReadReply();
技术分享                if (!(iReplyCode == 226 || iReplyCode == 250))
技术分享                {
技术分享                    throw new IOException(strReply.Substring(4));
技术分享                }
技术分享            }
技术分享        }
技术分享
技术分享        #endregion
技术分享
技术分享        #region 目录操作
技术分享        /// <summary>
技术分享        /// 创建目录
技术分享        /// </summary>
技术分享        /// <param name="strDirName">目录名</param>
技术分享        public void MkDir(string strDirName)
技术分享        {
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            SendCommand("MKD " + strDirName);
技术分享            if (iReplyCode != 257)
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享        }
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 删除目录
技术分享        /// </summary>
技术分享        /// <param name="strDirName">目录名</param>
技术分享        public void RmDir(string strDirName)
技术分享        {
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            SendCommand("RMD " + strDirName);
技术分享            if (iReplyCode != 250)
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享        }
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 改变目录
技术分享        /// </summary>
技术分享        /// <param name="strDirName">新的工作目录名</param>
技术分享        public void ChDir(string strDirName)
技术分享        {
技术分享            if (strDirName.Equals(".") || strDirName.Equals(""))
技术分享            {
技术分享                return;
技术分享            }
技术分享            if (!bConnected)
技术分享            {
技术分享                Connect();
技术分享            }
技术分享            SendCommand("CWD " + strDirName);
技术分享            if (iReplyCode != 250)
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享            this.strRemotePath = strDirName;
技术分享        }
技术分享
技术分享        #endregion
技术分享
技术分享        #region 内部变量
技术分享        /// <summary>
技术分享        /// 服务器返回的应答信息(包含应答码)
技术分享        /// </summary>
技术分享        private string strMsg;
技术分享        /// <summary>
技术分享        /// 服务器返回的应答信息(包含应答码)
技术分享        /// </summary>
技术分享        private string strReply;
技术分享        /// <summary>
技术分享        /// 服务器返回的应答码
技术分享        /// </summary>
技术分享        private int iReplyCode;
技术分享        /// <summary>
技术分享        /// 进行控制连接的socket
技术分享        /// </summary>
技术分享        private Socket socketControl;
技术分享        /// <summary>
技术分享        /// 传输模式
技术分享        /// </summary>
技术分享        private TransferType trType;
技术分享        /// <summary>
技术分享        /// 接收和发送数据的缓冲区
技术分享        /// </summary>
技术分享        private static int BLOCK_SIZE = 512;
技术分享        Byte[] buffer = new Byte[BLOCK_SIZE];
技术分享        /// <summary>
技术分享        /// 编码方式(为防止出现中文乱码采用 GB2312编码方式)
技术分享        /// </summary>
技术分享        Encoding GB2312 = Encoding.GetEncoding("gb2312");
技术分享        #endregion
技术分享
技术分享        #region 内部函数
技术分享        /// <summary>
技术分享        /// 将一行应答字符串记录在strReply和strMsg
技术分享        /// 应答码记录在iReplyCode
技术分享        /// </summary>
技术分享        private void ReadReply()
技术分享        {
技术分享            strMsg = "";
技术分享            strReply = ReadLine();
技术分享            iReplyCode = Int32.Parse(strReply.Substring(0, 3));
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 建立进行数据连接的socket
技术分享        /// </summary>
技术分享        /// <returns>数据连接socket</returns>
技术分享        private Socket CreateDataSocket()
技术分享        {
技术分享            SendCommand("PASV");
技术分享            if (iReplyCode != 227)
技术分享            {
技术分享                throw new IOException(strReply.Substring(4));
技术分享            }
技术分享            int index1 = strReply.IndexOf(‘(‘);
技术分享            int index2 = strReply.IndexOf(‘)‘);
技术分享            string ipData =
技术分享            strReply.Substring(index1 + 1, index2 - index1 - 1);
技术分享            int[] parts = new int[6];
技术分享            int len = ipData.Length;
技术分享            int partCount = 0;
技术分享            string buf = "";
技术分享            for (int i = 0; i < len && partCount <= 6; i++)
技术分享            {
技术分享                char ch = Char.Parse(ipData.Substring(i, 1));
技术分享                if (Char.IsDigit(ch))
技术分享                    buf += ch;
技术分享                else if (ch != ‘,‘)
技术分享                {
技术分享                    throw new IOException("Malformed PASV strReply: " +
技术分享                    strReply);
技术分享                }
技术分享                if (ch == ‘,‘ || i + 1 == len)
技术分享                {
技术分享                    try
技术分享                    {
技术分享                        parts[partCount++] = Int32.Parse(buf);
技术分享                        buf = "";
技术分享                    }
技术分享                    catch (Exception)
技术分享                    {
技术分享                        throw new IOException("Malformed PASV strReply: " +
技术分享                         strReply);
技术分享                    }
技术分享                }
技术分享            }
技术分享            string ipAddress = parts[0] + "." + parts[1] + "." +
技术分享            parts[2] + "." + parts[3];
技术分享            int port = (parts[4] << 8) + parts[5];
技术分享            Socket s = new
技术分享            Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
技术分享            IPEndPoint ep = new
技术分享            IPEndPoint(IPAddress.Parse(ipAddress), port);
技术分享            try
技术分享            {
技术分享                s.Connect(ep);
技术分享            }
技术分享            catch (Exception)
技术分享            {
技术分享                throw new IOException("Can‘t connect to remote server");
技术分享            }
技术分享            return s;
技术分享        }
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 关闭socket连接(用于登录以前)
技术分享        /// </summary>
技术分享        private void CloseSocketConnect()
技术分享        {
技术分享            if (socketControl != null)
技术分享            {
技术分享                socketControl.Close();
技术分享                socketControl = null;
技术分享            }
技术分享            bConnected = false;
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 读取Socket返回的所有字符串
技术分享        /// </summary>
技术分享        /// <returns>包含应答码的字符串行</returns>
技术分享        private string ReadLine()
技术分享        {
技术分享            while (true)
技术分享            {
技术分享                int iBytes = socketControl.Receive(buffer, buffer.Length, 0);
技术分享                strMsg += GB2312.GetString(buffer, 0, iBytes);
技术分享                if (iBytes < buffer.Length)
技术分享                {
技术分享                    break;
技术分享                }
技术分享            }
技术分享            char[] seperator = { ‘\n‘ };
技术分享            string[] mess = strMsg.Split(seperator);
技术分享            if (strMsg.Length > 2)
技术分享            {
技术分享                strMsg = mess[mess.Length - 2];
技术分享                //seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
技术分享                //但也会分配为空字符串给后面(也是最后一个)字符串数组,
技术分享                //所以最后一个mess是没用的空字符串
技术分享                //但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
技术分享            }
技术分享            else
技术分享            {
技术分享                strMsg = mess[0];
技术分享            }
技术分享            if (!strMsg.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
技术分享            {
技术分享                return ReadLine();
技术分享            }
技术分享            return strMsg;
技术分享        }
技术分享
技术分享
技术分享        /// <summary>
技术分享        /// 发送命令并获取应答码和最后一行应答字符串
技术分享        /// </summary>
技术分享        /// <param name="strCommand">命令</param>
技术分享        private void SendCommand(String strCommand)
技术分享        {
技术分享            Byte[] cmdBytes =
技术分享            GB2312.GetBytes((strCommand + "\r\n").ToCharArray());
技术分享            socketControl.Send(cmdBytes, cmdBytes.Length, 0);
技术分享            ReadReply();
技术分享        }
技术分享
技术分享        #endregion
技术分享    }
技术分享}
技术分享


当然,大家还要看看Main方法
技术分享using System;
技术分享using System.Collections.Generic;
技术分享using System.Text;
技术分享using System.IO;
技术分享
技术分享namespace ftpGet
技术分享{
技术分享    class Program
技术分享    {
技术分享        static string remotingFolder = System.Configuration.ConfigurationSettings.AppSettings["remotingFolder"];  //远程ftp文件目录
技术分享        static string localFolder = System.Configuration.ConfigurationSettings.AppSettings["localFolder"];  //要下载到的本地目录
技术分享        static string ftpServer = System.Configuration.ConfigurationSettings.AppSettings["ftpServer"];  //ftp服务器
技术分享        static string user = System.Configuration.ConfigurationSettings.AppSettings["user"];  //用户名
技术分享        static string pwd = System.Configuration.ConfigurationSettings.AppSettings["pwd"];  //密码
技术分享        static string port = System.Configuration.ConfigurationSettings.AppSettings["port"];  //端口
技术分享        static void Main(string[] args)
技术分享        {
技术分享            FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
技术分享            client.Connect();
技术分享            GetFolder("*", remotingFolder, client, CreateFolder());
技术分享            client.DisConnect();
技术分享            ClearFolder();
技术分享            Console.WriteLine("下载完毕");
技术分享            System.Threading.Thread.Sleep(3000);
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 在本地目录下创建一个以日期为名称的目录,我做这个ftp的主要目的是为了每天都备份
技术分享        /// </summary>
技术分享        /// <returns>创建的目录名</returns>
技术分享        private static string CreateFolder()
技术分享        {
技术分享            string folder=localFolder + "\\"+DateTime.Now.ToShortDateString();
技术分享            if (!Directory.Exists(folder))
技术分享                Directory.CreateDirectory(folder);
技术分享            
技术分享            return folder;
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 在下载结束后清空程序目录的多余文件
技术分享        /// </summary>
技术分享        private static void ClearFolder()
技术分享        {
技术分享            string folder = Environment.CurrentDirectory;
技术分享            string[] dictorys = Directory.GetFiles(folder);
技术分享            foreach (string dictory in dictorys)
技术分享            {
技术分享                FileInfo info = new FileInfo(dictory);
技术分享                if (info.Length == 0)
技术分享                    File.Delete(dictory);
技术分享            }
技术分享        }
技术分享
技术分享        /// <summary>
技术分享        /// 递归获取ftp文件夹的内容
技术分享        /// </summary>
技术分享        /// <param name="fileMark">文件标记</param>
技术分享        /// <param name="path">远程路径</param>
技术分享        /// <param name="client"></param>
技术分享        /// <param name="folder"></param>
技术分享        private static void GetFolder(string fileMark, string path, FTPClient client, string folder)
技术分享        {
技术分享            string[] dirs = client.Dir(path);  //获取目录下的内容
技术分享            client.ChDir(path);  //改变目录
技术分享            foreach (string dir in dirs)
技术分享            {
技术分享                string[] infos = dir.Split(‘ ‘);
技术分享                string info = infos[infos.Length - 1].Replace("\r", "");
技术分享                if (dir.StartsWith("d") && !string.IsNullOrEmpty(dir))  //为目录
技术分享                {
技术分享
技术分享                    if (!info.EndsWith(".") && !info.EndsWith(".."))  //筛选出真实的目录
技术分享                    {
技术分享                        Directory.CreateDirectory(folder + "\\" + info);
技术分享                        GetFolder(fileMark, path + "/" + info, client, folder + "\\" + info);
技术分享                        client.ChDir(path);
技术分享                    }
技术分享                }
技术分享                else if (dir.StartsWith("-r"))  //为文件
技术分享                {
技术分享                    string file = folder + "\\" + info;
技术分享                    if (File.Exists(file))  
技术分享                    {
技术分享                        long remotingSize = client.GetFileSize(info);
技术分享                        FileInfo fileInfo = new FileInfo(file);
技术分享                        long localSize = fileInfo.Length;
技术分享
技术分享                        if (remotingSize != localSize)  //短点续传
技术分享                        {
技术分享                            client.GetBrokenFile(info, folder, info, localSize);
技术分享                        }
技术分享                    }
技术分享                    else
技术分享                    {
技术分享                        client.GetFile(info, folder, info);  //下载文件
技术分享                        Console.WriteLine("文件" + folder + info + "已经下载");
技术分享                    }
技术分享                }
技术分享            }
技术分享
技术分享        }
技术分享    }
技术分享}
技术分享

配置文件
技术分享<?xml version="1.0" encoding="utf-8" ?>
技术分享<configuration>
技术分享  <appSettings>
技术分享    <add key="remotingFolder" value="/temp"/>
技术分享    <add key="localFolder" value="c:\temp"/>
技术分享    <add key="ftpServer" value="*"/>
技术分享    <add key="user" value="*"/>
技术分享    <add key="pwd" value="*"/>
技术分享    <add key="port" value="21"/>
技术分享  </appSettings>
技术分享</configuration>

c#上传下载ftp(支持断点续传)

标签:

原文地址:http://www.cnblogs.com/lvdongjie/p/5602111.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!