上篇文章讨论了C#从基于FTPS的FTP server下载数据 (FtpWebRequest 的使用)SSL 加密。不过细心的朋友应该可以发现FTPWebRequest 每次都是新生成一个request ( FTPWebRequest.create(uri) ), 这样对于一些复杂的需求,需要反复登陆,代码就会变得冗余啰嗦,那今天就和大家探讨一下如何包装FTPWebRequest类。如有好的想法或意见,希望各位大神老鸟多多指教。

 
先说一下我的需求:
 
去FTP Server 的一个指定路径下,找到更新时间最近的文件并下载。
那按照以上需求,就需要先去路径下,找到更新时间最近的文件,在根据文件名下载。 
 
这里封装一个FTPClient 类 (从网上找了一个FTPClient的壳子,忘记了原博客地址了,抱歉)
原理很简单,就是封装‘列出目录功能’和 ‘下载文件功能’。将用户名密码等放在FTPClient的属性中。
上码!
 
 using System.Collections.Generic;
using System;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security; namespace FtpClientBlogCase
{ #region "FTP client class"
public class FTPclient
{
#region "CONSTRUCTORS"
public FTPclient(string Hostname, string Username, string Password, bool EnableSSL)
{
this.Hostname = Hostname;
this.Username = Username;
this.Password = Password;
this.EnableSsl = EnableSSL;
}
#endregion #region "Directory functions"
public List<string> ListDirectory(string URI)
{
System.Net.FtpWebRequest ftp = GetRequest(URI);
//Set request to do simple list
ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectory; string str = GetStringResponse(ftp);
//replace CRLF to CR, remove last instance
str = str.Replace("\r\n", "\r").TrimEnd('\r');
//split the string into a list
List<string> result = new List<string>();
result.AddRange(str.Split('\r'));
return result;
}
#endregion #region "Download: File transfer FROM ftp server"
/// <summary>
/// Copy a file from FTP server to local
/// </summary>
/// <param name="sourceFilename">Target filename, if required</param>
/// <param name="localFilename">Full path of the local file</param>
/// <returns></returns>
/// <remarks>
/// Target can be blank (use same filename), or just a filename
/// (assumes current directory) or a full path and filename
/// 1.2 [HR] added CreateURI
/// </remarks>
public bool Download(string sourceFilename, string localFilename, bool PermitOverwrite)
{
//2. determine target file
FileInfo fi = new FileInfo(localFilename);
return this.Download(sourceFilename, fi, PermitOverwrite);
} /// <summary>
/// Version taking string/FileInfo
/// </summary>
/// <param name="sourceFilename"></param>
/// <param name="targetFI"></param>
/// <param name="PermitOverwrite"></param>
/// <returns></returns>
public bool Download(string sourceFilename, FileInfo targetFI, bool PermitOverwrite)
{
//1. check target
if (targetFI.Exists && !(PermitOverwrite))
{
throw (new ApplicationException("Target file already exists"));
} //2. check source
if (String.IsNullOrEmpty(sourceFilename))
{
throw (new ApplicationException("File not specified"));
}
System.Net.FtpWebRequest ftp = GetRequest(sourceFilename); //Set request to download a file in binary mode
ftp.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;
ftp.UseBinary = true; //open request and get response stream
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
//loop to read & write to file
responseStream.ReadTimeout = ;
using (FileStream fs = targetFI.OpenWrite())
{
try
{
byte[] buffer = new byte[**];
int read = ;
do
{
read = responseStream.Read(buffer, , buffer.Length);
fs.Write(buffer, , read);
fs.Flush();
} while (read != );
responseStream.Close();
fs.Flush();
fs.Close();
}
catch (Exception)
{
//catch error and delete file only partially downloaded
fs.Close();
//delete target file as it's incomplete
targetFI.Delete();
throw;
}
} responseStream.Close();
} response.Close();
} return true;
} #endregion #region "private supporting fns" //Get the basic FtpWebRequest object with the
//common settings and security
private FtpWebRequest GetRequest(string URI)
{
//create request
FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(URI);
//Set the login details
result.Credentials = GetCredentials();
// support for EnableSSL
result.EnableSsl = EnableSsl;
result.Timeout = ; ServicePoint sp = result.ServicePoint;
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(ValidateServerCertificate); return result;
} /// <summary>
/// Ensure chars in path are correctly escaped e.g. #
/// </summary>
/// <param name="path">path to escape</param>
/// <returns></returns>
private string GetEscapedPath(string path)
{
string[] parts;
parts = path.Split('/');
string result;
result = "";
foreach (string part in parts)
{
if (!string.IsNullOrEmpty(part))
result += @"/" + Uri.EscapeDataString(part);
}
return result;
} /// <summary>
/// Get the credentials from username/password
/// </summary>
/// <remarks>
/// Amended to store credentials on first use, for re-use
/// when using KeepAlive=true
/// </remarks>
private System.Net.ICredentials GetCredentials()
{
if (_credentials == null)
_credentials = new System.Net.NetworkCredential(Username, Password);
return _credentials;
} /// <summary>
/// stored credentials
/// </summary>
private System.Net.NetworkCredential _credentials = null; /// <summary>
/// Obtains a response stream as a string
/// </summary>
/// <param name="ftp">current FTP request</param>
/// <returns>String containing response</returns>
/// <remarks>
/// FTP servers typically return strings with CR and
/// not CRLF. Use respons.Replace(vbCR, vbCRLF) to convert
/// to an MSDOS string
/// 1.1: modified to ensure accepts UTF8 encoding
/// </remarks>
private string GetStringResponse(FtpWebRequest ftp)
{
//Get the result, streaming to a string
string result = "";
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
long size = response.ContentLength;
using (Stream datastream = response.GetResponseStream())
{
using (StreamReader sr = new StreamReader(datastream, System.Text.Encoding.UTF8))
{
result = sr.ReadToEnd();
sr.Close();
} datastream.Close();
} response.Close();
} return result;
} /// <summary>
/// Gets the size of an FTP request
/// </summary>
/// <param name="ftp"></param>
/// <returns></returns>
/// <remarks></remarks>
private long GetSize(FtpWebRequest ftp)
{
long size;
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
{
size = response.ContentLength;
response.Close();
} return size;
} private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
} #endregion #region Properties public string Hostname { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool EnableSsl { get; set; } #endregion }
#endregion }

FTPClient.cs

 using System;
using System.Configuration;
using System.Linq; namespace FtpClientBlogCase
{
class Program
{
static void Main(string[] args)
{
DownloadFileFromFTP.DownloadFileFromNetwork();
Console.WriteLine("Done");
}
} public class DownloadFileFromFTP
{
public static void DownloadFileFromNetwork()
{
var fullDataServer = "XXX";
var userName = "XXX";
var password = "XXX";
var fc = new FTPclient(fullDataServer, userName, password, true);
var list = fc.ListDirectory(fullDataServer);
Console.WriteLine("The file is downloading, please wait...");
fc.Download(fullDataServer + list.Last(), list.Last(), true); }
}
}

Program.cs

在类FTPClient中,private FtpWebRequest GetRequest(string URI) 是最重要的方法,它为每一个功能提供了一个FtpWebRequest对象,避免了每次生成request对象的冗余冗余代码。

包装FTPWebRequest类的更多相关文章

  1. 【自制工具类】struts返回json数据包装格式类

    自己写的一个给struts返回的json数据包装格式类,不喜勿喷,原创,需在项目中引入com.alibaba.fastjson的jar包 先看下效果(这里没有使用msg,有兴趣的往下看): 上demo ...

  2. java基本类型和包装器类

    java是一种面向对象语言,java中的类把方法与数据连接在一起,并构成了自包含式的处理单元.但在java中不能定义基本类型(primitive type),为了能将基本类型视为对象来处理,并能连接相 ...

  3. 走近Java之包装器类Integer

    前几天,有个同事问了我一个关于Integer类赋值的问题,很有意思,我们一起来看一下(如果有说的不正确的地方,欢迎大家指正). 如上图,同样是赋值,但是两次比较的结果完全不同.我们走近了解一下. 在I ...

  4. 课堂所讲整理:包装&工具类

    package org.hanqi.array; import java.util.Random; public class BaoZhuang { public static void main(S ...

  5. 用于JS日期格式化,以及简单运算的Date包装工具类

    1. [文件] yDate.js/** * | yDate.js | Copyright (c) 2013 yao.yl | email: redrainyi@126.com | Date: 2012 ...

  6. Python-面向对象(类)一

    一.如何创建类 class cls: pass 二.创建方法 构造方法: __init__(self, arg) obj = 类('a1') 普通方法: obj = 类('xxx') obj.普通方法 ...

  7. Spring源码分析——资源访问利器Resource之实现类分析

    今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...

  8. 在C#中使用C++编写的类

    现在在Windows下的应用程序开发,VS.Net占据了绝大多数的份额.因此很多以前搞VC++开发的人都转向用更强大的VS.Net.在这种情况下,有很多开发人员就面临了如何在C#中使用C++开发好的类 ...

  9. Python全栈--9.1--面向对象进阶-super 类对象成员--类属性- 私有属性 查找源码类对象步骤 类特殊成员 isinstance issubclass 异常处理

    上一篇文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象 ...

随机推荐

  1. dva框架使用mock.js模拟数据 + fetch请求数据

    what DVA? Dva是基于Redux做了一层封装,对于React的state管理,有很多方案,我选择了轻量.简单的Dva. dva 可以很方便就使用mock.js进行数据的模拟. 只需要三步,即 ...

  2. ST-1之乱码bug

    我印象最深刻的一个错误就是乱码.上学期末做web期末作业时候,我就遇到了好多乱码问题.乱码问题并不是程序本身的逻辑错误,但是却让程序的可用性非常的差.只有输入英文时才能判断结果的正确与否.而且编译器又 ...

  3. 高性能linux服务器内核调优

    高性能linux服务器内核调优 首先,介绍一下两个命令1.dmesg 打印系统信息.有很多同学们服务器出现问题,看了程序日志,发现没啥有用信息,还是毫无解决头绪,这时候,你就需要查看系统内核抛出的异常 ...

  4. oracle一直不确定的distinct多字段处理情况整理

    第一步,建一个表,表数据如下: 第二步:发现叫豆豆的是两只狗,一只是金毛犬,一只狼青. 如果我用 select 宠物名称,宠物大类 from test_1;返回结果就只有一条. 如果我用 select ...

  5. (坑)django test在多线程下的问题

    问题描述: 使用django自带的test做测试,尝试去数据库中取数据,主线程中没有问题,非主线程中取不到数据. 示例代码: class MyTestCase(TestCase): def setUp ...

  6. poj1797 Heavy Transportation Dijkstra算法的简单应用

    题目链接:http://poj.org/problem?id=1797 题目就是求所有可达路径的其中的最小值边权的最大值 即对于每一条能够到达的路径,其必然有其最小的承载(其实也就是他们自身的最大的承 ...

  7. 访问servlet的路径问题

    一.url-pattern的三种配置 在web.xml配置文件中配置有关Servlet的时候,<url-pattern>标签是用于配置当前Servlet拦截的路径,也就是说,客户端浏览器访 ...

  8. [ios]quartz2d画板功功能实现核心代码

    //触摸开始 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //    1,获取对 ...

  9. Spring事务处理

    事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位. 数据库向用户提供保存当前程序状态的方法,叫事务提交(commit): ...

  10. Alamofire源码解读系列(十二)之请求(Request)

    本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...