zoukankan      html  css  js  c++  java
  • C# 实现 微软WebRequestMethods.Ftp类中的FTP操作功能

    先奉献一个测试地址,ftp内的文件请勿删除,谢谢

    FtpEntity fe = new FtpEntity("wjshan0808.3vhost.net", "wjshan0808", "1234567890");

    由于代码量较多,只抽出一部分,详细代码请移步  ftp://wjshan0808.3vhost.net/FtpEntity/或 随笔后面有源码下载地址

    部分字段
            #region fields
            private const string PATTERN = @"^([dlb-])([rwx-]{9})s+(d{1,})s+(w+)s+(.+?)s+(d{1,})s+(.+?)s+(d{1,2})s+(d{2}:?d{2})s+(.+)$";
            private const int DYNAMICINCREASEVALUE = 1024 * 512;//512KB
            private const int DYNAMICIMCEPTVALUE = 1024 * 64;//64KB;
            private static ReaderWriterLock _lok = new ReaderWriterLock();
            private int _dynamicBufferSize = 0;
            private bool _isDownloadCheck = true;
            private bool _isUploadCheck = false;
            private Dictionary<Uri, long> _dicFileSize = null;
            private int _sendBufferSize = 1024 * 128;//128KB
            #endregion
            #region props
            /// <summary>
            /// 当文件数据上传完成时发生
            /// </summary>
            public event UploadCompletedEventHandler UploadCompleted;
            /// <summary>
            /// 获取或设置上传数据的缓冲区大小
            /// </summary>
            public int SendBufferSize
            {
                get { return _sendBufferSize; }
                set
                {
                    if (value < 1)
                        value = 1024 * 128;
                    _lok.AcquireWriterLock(1000);
                    try
                    {
                        _sendBufferSize = value;
                    }
                    finally
                    {
                        _lok.ReleaseWriterLock();
                    }
                }
            }
            /// <summary>
            /// 获取请求FTP服务器的协议地址
            /// </summary>
            public string Address
            {
                get { return string.Format("ftp://{0}:{1}", _address, Port); }
            }
            /// <summary>
            /// 获取或设置相对FTP根目录的绝对路径,默认为Ftp根目录
            /// </summary>
            public string AbsolutePath
            {
                get { return _absolutePath; }
                set
                {
                    IsNull(ref value);
                    while (value.StartsWith("/"))
                    {
                        value = value.TrimStart('/');
                    }
                    if (value.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
                        throw new ArgumentException("RelativeUrl:Invalid Value");
                    _absolutePath = value;
                }
            }
            /// <summary>
            /// 获取请求FTP服务器的解析地址
            /// </summary>
            public string ResolveUrl
            {
                get { return Path.Combine(Address, AbsolutePath).Replace(@"", "/"); }
            }
            #endregion

    1.获取详细列表

            /// <summary>
            /// 获取 AbsolutePath (属性值)下的文件(夹)的详细列表
            /// </summary>
            /// <param name="total">总用量</param>
            /// <param name="absolutePath">目标地址</param>
            /// <returns>文件(夹)详细信息</returns>
            public FtpDirectoryDetails[] ListDirectoryDetails(out int total, string absolutePath = null)
            {
                if (absolutePath != null && absolutePath != string.Empty)
                    AbsolutePath = absolutePath;
                using (FtpWebResponse response = SyncInternalCommon(WebRequestMethods.Ftp.ListDirectoryDetails))
                {
                    total = 0;
                    IList<FtpDirectoryDetails> fddes = new List<FtpDirectoryDetails>(16);
                    StreamReader reader = null;
                    try
                    {
                        if (response.StatusCode == FtpStatusCode.OpeningData)
                        {
                            reader = new StreamReader(response.GetResponseStream(), Encoding.Default, true);
                        }
                        if (reader == null) throw new ArgumentNullException("reader");
                        while (!reader.EndOfStream)
                        {
                            string line = reader.ReadLine();
                            MatchCollection mc = Regex.Matches(line, PATTERN, RegexOptions.CultureInvariant);
                            if (mc.Count == 1)
                            {
                                object[] tmp = new object[11];
                                mc[0].Groups.CopyTo(tmp, 0);
                                fddes.Add(new FtpDirectoryDetails(tmp));
                            }
                            else //total
                            {
                                total = int.Parse(Regex.Match(line, @"d{1,}", RegexOptions.CultureInvariant).Value);
                            }
                        }
                        return fddes.ToArray();
                    }
                    catch (Exception ex)
                    {
                        Log(ex);
                        throw ex;
                    }
                    finally
                    {
                        if (reader != null)
                            reader.Close();
                    }
                }
            }
    View Code

    目录详细信息类

        /// <summary>
        /// 目录文件信息
        /// </summary>
        public struct FtpDirectoryDetails
        {
            public FtpDirectoryType Type { get; set; }
            public FtpDirectoryAccess[] Access { get; set; }
            public short Count { get; set; }
            public string User { get; set; }
            public string Group { get; set; }
            public long Size { get; set; }
            public DateTime LastModified { get; set; }
            //public string Year { get; set; }
            public string Name { get; set; }
    
    
            public FtpDirectoryDetails(object[] details)
            {
                Type = FtpDirectoryType.Unknow;
                Access = new FtpDirectoryAccess[3] { FtpDirectoryAccess.None, FtpDirectoryAccess.None, FtpDirectoryAccess.None };
    
                Count = short.Parse(details[3].ToString());
                User = details[4].ToString();
                Group = details[5].ToString();
    
                Size = long.Parse(details[6].ToString());
    
                LastModified = DateTime.MinValue;
    
                Name = details[10].ToString();
                //
                SetType(details[1].ToString());
                SetAccess(details[2].ToString());
                SetLastModified(details[7].ToString(), details[8].ToString(), details[9].ToString());
            }
    
            private void SetLastModified(string month, string day, string time0year)
            {
                StringBuilder sb = new StringBuilder(16);
                bool contains = time0year.Contains(":");
                sb.Append(contains ? DateTime.Now.Year.ToString() : time0year);
                sb.Append(" ");
                sb.Append(string.Format("{0:00}", SetMonth(month)));
                sb.Append(" ");
                sb.Append(string.Format("{0:00}", day));
                sb.Append(" ");
                sb.Append(contains ? time0year : "00:00");
                sb.Append(":00");
                LastModified = DateTime.Parse(sb.ToString());
            }
    
            /// <summary>
            /// 1.英文
            /// 2.阿拉伯数字
            /// 3.两位阿拉伯数字
            /// 4.(2,3)+中文
            /// </summary>
            /// <param name="month"></param>
            /// <returns></returns>
            private object SetMonth(string month)
            {
                if (month[month.Length - 1] <= 57)//最后一位是数字 
                    return month;
    
                if (month[0] <= 57)//第一位是数字
                    return month.Substring(0, month.Length - 1);
    
                if ("January".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Jan
                    return 1;
                else if ("February".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Feb
                    return 2;
                else if ("March".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Mar
                    return 3;
                else if ("April".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Apr
                    return 4;
                else if ("May".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//May
                    return 5;
                else if ("June".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Jun
                    return 6;
                else if ("July".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Jul
                    return 7;
                else if ("August".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Aug
                    return 8;
                else if ("September".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Sep
                    return 9;
                else if ("October".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Oct
                    return 10;
                else if ("November".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Nov
                    return 11;
                else
                    //("December".StartsWith(month, StringComparison.CurrentCultureIgnoreCase))//Dec
                    return 12;
            }
    
            private void SetAccess(string access)
            {
                for (int i = 0; i < access.Length; i += 3)
                {
                    FtpDirectoryAccess acc = FtpDirectoryAccess.None;
                    for (int j = i; j < (i + 3); j++)
                    {
                        switch (access[j])
                        {
                            case 'r':
                                acc |= FtpDirectoryAccess.Read;
                                break;
                            case 'w':
                                acc |= FtpDirectoryAccess.Write;
                                break;
                            case 'x':
                                acc |= FtpDirectoryAccess.Execute;
                                break;
                            default:// '-':
                                acc |= FtpDirectoryAccess.None;
                                break;
                        }
                    }
                    Access[i / 3] = acc;
                }
            }
            private void SetType(string type)
            {
                switch (type)
                {
                    case "d":
                        Type = FtpDirectoryType.Folder;
                        break;
                    case "-":
                        Type = FtpDirectoryType.File;
                        break;
                    case "l":
                        Type = FtpDirectoryType.Link;
                        break;
                    case "b":
                        Type = FtpDirectoryType.Block;
                        break;
                    default:
                        Type = FtpDirectoryType.Unknow;
                        break;
                }
            }
        }

    2.上传

            #region UploadCommon
            protected void SyncUploadCommon(string file, bool withUnique = false, long offset = 0)
            {
                CheckUrl(file, withUnique);
                FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
                if (offset > 0)
                    fs.Seek(offset, SeekOrigin.Begin);
                FtpWebRequest request = WebRequest.Create(ResolveUrl) as FtpWebRequest;
                request.Credentials = Credential;
                request.UsePassive = false;
                request.ContentLength = fs.Length;
                if (withUnique && offset == 0)
                    request.Method = WebRequestMethods.Ftp.UploadFileWithUniqueName;
                else
                    request.Method = offset > 0 ? WebRequestMethods.Ftp.AppendFile : WebRequestMethods.Ftp.UploadFile;
                string path = request.RequestUri.AbsolutePath;
                Stream stream = null;
                BinaryReader reader = null;
                FtpTransmissionStatus status = FtpTransmissionStatus.Ok;
                try
                {
                    stream = request.GetRequestStream();
                    if (stream == null)
                        throw new ArgumentNullException("stream");
                    reader = new BinaryReader(fs, Encoding.Default);
                    if (reader == null)
                        throw new ArgumentNullException("reader");
                    while (reader.PeekChar() != -1)
                    {
                        byte[] bt = reader.ReadBytes(_sendBufferSize);
                        stream.Write(bt, 0, bt.Length);
                        stream.Flush();
                    }
                    //GetResponse after Close
    
                }
                catch (Exception ex)
                {
                    status = FtpTransmissionStatus.Error;
                    Log(ex);
                    //throw ex;
                }
                finally
                {
                    if (reader != null)
                        reader.Close();
                    if (stream != null)
                        stream.Close();
    
                    if (UploadCompleted != null)
                    {
                        Thread.Sleep(124);
                        UploadCompleted(new object(),
                            new UploadCompletedEventArgs()
                            {
                                Length = (!withUnique && IsUploadCheck) ? GetFileSize(path) : -1,//异步时文件路径会改变
                                Path = path,
                                FileName = (!withUnique) ? Path.GetFileName(path) : string.Empty,
                                UploadStatus = status
                            });
                    }
                }
            }
            protected void AsyncUploadCommon(string file, long offset = 0, bool withUnique = false)
            {
                CheckUrl(file, withUnique);
                FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
                if (offset > 0)
                    fs.Seek(offset, SeekOrigin.Begin);
                FtpWebRequest request = WebRequest.Create(ResolveUrl) as FtpWebRequest;
                request.Credentials = Credential;
                request.UsePassive = false;
                request.ContentLength = fs.Length;
                if (withUnique && offset == 0)
                    request.Method = WebRequestMethods.Ftp.UploadFileWithUniqueName;
                else
                    request.Method = offset > 0 ? WebRequestMethods.Ftp.AppendFile : WebRequestMethods.Ftp.UploadFile;
    
                FtpState state = new FtpState() { Request = request, FileStream = fs, Path = request.RequestUri.AbsolutePath, Unique = withUnique };
                try
                {
                    IAsyncResult iar = request.BeginGetRequestStream(new AsyncCallback(UploadCallBack), state);
                }
                catch (Exception ex)
                {
                    Log(ex);
                    state.Dispose();
                    //throw ex;
                }
            }
            protected void UploadCallBack(IAsyncResult ar)
            {
                FtpState state = ar.AsyncState as FtpState;
                if (state == null) throw new ArgumentNullException("state");
                if (state.Request == null) throw new ArgumentNullException("state.Request");
                if (state.FileStream == null) throw new ArgumentNullException("state.FileStream");
                FtpTransmissionStatus status = FtpTransmissionStatus.Ok;
                try
                {
                    if (ar.IsCompleted)
                    {
                        Stream stream = state.Request.EndGetRequestStream(ar);
                        if (stream == null)
                            throw new ArgumentNullException("stream");
                        state.Stream = stream;
                    }
                    while (IsReadToEnd)
                    {
                        byte[] bt = new byte[SendBufferSize];
                        int length = state.FileStream.Read(bt, 0, bt.Length);
                        if (length == 0) break;
                        IAsyncResult iar = state.Stream.BeginWrite(bt, 0, length, null, null);
                        state.Stream.EndWrite(iar);
                        state.Stream.Flush();
                    }
                    //GetResponse after Close
    
                }
                catch (Exception ex)
                {
                    status = FtpTransmissionStatus.Error;
                    Log(ex);
                    //throw ex;
                }
                finally
                {
                    string path = state.Path;
                    bool withUnique = state.Unique;
                    state.Dispose();
    
                    if (UploadCompleted != null)
                    {
                        Thread.Sleep(124);
                        UploadCompleted(new object(),
                            new UploadCompletedEventArgs()
                            {
                                Length = (!withUnique && IsUploadCheck) ? GetFileSize(path) : -1,//异步时文件路径会改变
                                Path = path,
                                FileName = (!withUnique) ? Path.GetFileName(path) : string.Empty,
                                UploadStatus = status
                            });
                    }
                }
            }
            #endregion
    View Code

    辅助函数

            private int DynamicBufferSize(int length)
            {
                if (length == 0)
                    length += DYNAMICIMCEPTVALUE;
                if (length == _dynamicBufferSize)
                    length += DYNAMICINCREASEVALUE;
                length += -_dynamicBufferSize;
                if ((length + _dynamicBufferSize) <= 0)
                    length += DYNAMICIMCEPTVALUE;
                return Interlocked.Add(ref _dynamicBufferSize, length);
            }
            private void CheckPath(string path)
            {
                if (path == null)
                    throw new ArgumentNullException(path);
                if (path.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
                    throw new ArgumentException("Invalid Path");
                if (!File.Exists(path))
                    throw new FileNotFoundException();
            }
            private string CheckName(string value)
            {
                if (value == null || value == string.Empty)
                    throw new ArgumentNullException(value);
                if (value.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                    throw new WarningException(value + "Invalid FileName");
                return value;
            }
            private void CheckUrl(string file, bool withUnique)
            {
                string name = Path.GetFileName(file);
                string uploadname = Path.GetFileName(AbsolutePath);
                if (uploadname == string.Empty)
                {
                    AbsolutePath = AbsolutePath.TrimEnd(new char[] { '/' }) + "/" + name;
                }
            }
            private void IsNull(ref string value)
            {
                if (value != null) return;
                value = string.Empty;
            }

    测试代码

            private void btnTest_Click(object sender, EventArgs e)
            {
                fe.UploadCompleted += new UploadCompletedEventHandler(Fe_UploadCompleted);
                try
                {
                    fe.AbsolutePath = "FtpEntity";
                    Files(@"C:UsersAdministratorDesktopFtpEntityFtpEntity");
                }
                catch (Exception ex)
                {
                }
            }
            public void Files(string dir)
            {
                DirectoryInfo di = new DirectoryInfo(dir);
                foreach (DirectoryInfo item in di.GetDirectories())
                {
                    string tmp1 = fe.AbsolutePath;
                    fe.AbsolutePath += "/" + item.Name;
                    fe.MakeDirectory();
                    Files(item.FullName);
                    fe.AbsolutePath = tmp1;
                }
                foreach (FileInfo fi in di.GetFiles())
                {
                    string tmp2 = fe.AbsolutePath;
                    fe.AbsolutePath += "/" + fi.Name;
                    fe.AsyncUploadFile(fi.FullName);
                    fe.AbsolutePath = tmp2;
                }
            }
            private void Fe_UploadCompleted(object sender, UploadCompletedEventArgs e)
            {
                if (rtxtLog.InvokeRequired)
                {
                    rtxtLog.Invoke(new UploadCompletedEventHandler(Fe_UploadCompleted), new object[] { sender, e });
                }
                else
                {
                    rtxtLog.Text += Environment.NewLine + "-----------";
                    rtxtLog.Text += e.Length + Environment.NewLine
                        + e.FileName + Environment.NewLine
                        + e.FileSize + Environment.NewLine
                        + e.Path + Environment.NewLine
                        + e.UploadStatus;
                    rtxtLog.Text += Environment.NewLine + "-----------";
                }
            }

    源文件地址 http://pan.baidu.com/s/1o6rLR2y

  • 相关阅读:
    痞子衡嵌入式:MCUBootFlasher v3.0发布,为真实的产线操作场景而生
    架构设计 | 分布式体系下,服务分层监控策略
    Hadoop框架:单服务下伪分布式集群搭建
    大数据简介,技术体系分类整理
    架构设计 | 基于Seata中间件,微服务模式下事务管理
    编程体系结构(03):Java集合容器
    SpringBoot2 集成日志,复杂业务下的自定义实现
    结构与算法(02):队列和栈结构
    架构设计 | 基于消息中间件,图解柔性事务一致性
    编程体系结构(02):Java异常体系
  • 原文地址:https://www.cnblogs.com/wjshan0808/p/4945645.html
Copyright © 2011-2022 走看看