代码改变世界

[外文翻译]Simple FTP demo application using C#.Net 2.0

2007-08-23 11:02  水随风  阅读(1029)  评论(1)    收藏  举报

虽然英文不怎么 样,但为了锻炼自己还是努力学习英文。平时看一些codeproject英文文章的时候也顺便翻译了一下

翻译的比较差,但也是自己学习的过程

=================================================

介绍:

Microsoft .net framwork 1.02.0的升级中更好的支持了FTP,这些天我不得不去靠那些适合我需要得类库,但有一点很确定,使用.net framework中的类是件非常高兴的事。代码中没有去专门的写出可以重用的类,但是你却可以很容易的去使用那些代码段去完成你确切需要的功能。因此代码中的每一个函数(包括上传,下载,删除等等)能够很容易去分离开来重构后达到重用的目的。这篇文章主要的目的在于用C#语言写描述的一个简单的关于.net2.0平台下的ftp的使用;也许正因为一个新的角色加入了.net的大环境中或者是说新增的这部分有用的类库,编程会变得更加方便,那么这部分的.net类库也会更多关注

 

背景:

当我在工作中遇到要写FTP模块的时候,但是需求改变了我不得不去用.net1.1去编码。但我相信在安装.net2.0会更好支持FTP的。

 

代码引用

 

不要忘记添加下面的引用

using System.Net;

using System.IO;

 

下面的步骤是用FtpWebRequest对象请求FTP执行的一般过程

 

1.     创建一个包含FTP服务器的URI地址的FtpWebRequest对象。

2.     设定执行FTP的方法操作(上传,下载,等等)

3.     设定FTP网页请求的属性(SSL支持,传输模式 等等)

4.     设定登录验证(用户名,密码)

5.     执行请求

6.     接受回发的数据流(如果要求)

7.     关闭FTP请求和其他打开的数据流

 

 

有一点要注意的就是当你编写你的FTP应用程序的时候应该适合你FTP服务器的特殊设置去设置你程序的FTP请求,FtpWebRequest对象提供了许多属性去设置。

 

上传的函数例子如下:

       首先,创建的URI是包含文件名的(包含目录结构)FTP地址。URL被用来创建FtpWebRequest实例。

 

FtpWebRequest的属性的设置,决定于FTP的请求设置。一些重要的属性设置是:

 

验证(Credentials)-登录FTP服务器时需要特定的账号和密码。

保持激活(KeepAlive)-在请求完成后应该关闭连接,但是默认的是设置为激活状态

二进制传输(UseBinary)-意思是文件传输的数据类型。两种文件传输类型的方法是二进制和ASCII。在比特的程度上字节的第八位是不同的含义、ASCII用第八位的比特表示错误信息,而二进制是整个字节的8位都是表示这个含义。因此用ASCII码传输的时候要小心了。简单点说,所有的那些用文本打开和写的那些文件用ASCII保存。可执行的程序,格式化的文档应该用二进制模式传输。很多时候ASCII文件用二进制模式比较好。

 

被动模式(USEPASSIVE)-使用主动和被动模式。早期的FTP客户端用的都是主动模式,但是今天很多的随机端口被防火墙阻挡了,主动模式可能会登录失败。在这种情况下被动模式FTP变得有用。但是任然导致在服务器出现一些问题。

在客户端的高端口的请求也会被防火墙阻挡。但是一旦FTP服务器需要满足大量客户端请求的时候,他们几乎需要去支持被动模式。为什么被动模式被认为是安全的原因就是它不确定所有的数据流来自网络的客户端而非来自服务端。

 

内容长度 Contentlength)-这个属性的设置对我们请求的服务端有用而对我们(客户端)无用,因为FtpWebRequest常常忽略这些属性的值,因此在多数情况下它对我们毫无意义。但是如果我们设置这些属性,FTP服务器会获得一个关于它所期望的(如果上传)文件大小的信息。

 

方法(Method)-意思是说在当前请求的操作(命令,如 上传,下载,文件列表,等等)它是设置一个值定义WebRequestMethods.Ftp结构

 1 private void Upload(string filename)
 2 {
 3 FileInfo fileInf = new FileInfo(filename);
 4 string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
 5 FtpWebRequest reqFTP;
 6 // Create FtpWebRequest object from the Uri provided
 7 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(
 8 "ftp://" + ftpServerIP + "/" + fileInf.Name));
 9 // Provide the WebPermission Credintials
10 reqFTP.Credentials = new NetworkCredential(ftpUserID,
11 ftpPassword);
12 // By default KeepAlive is true, where the control connection is
13 // not closed after a command is executed.
14 reqFTP.KeepAlive = false;
15 // Specify the command to be executed.
16 reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
17 // Specify the data transfer type.
18 reqFTP.UseBinary = true;
19 // Notify the server about the size of the uploaded file
20 reqFTP.ContentLength = fileInf.Length;
21 // The buffer size is set to 2kb
22 int buffLength = 2048;
23 byte[] buff = new byte[buffLength];
24 int contentLen;
25 // Opens a file stream (System.IO.FileStream) to read
26 the file to be uploaded
27 FileStream fs = fileInf.OpenRead();
28 try
29 {
30 // Stream to which the file to be upload is written
31 Stream strm = reqFTP.GetRequestStream();
32 // Read from the file stream 2kb at a time
33 contentLen = fs.Read(buff, 0, buffLength);
34 // Till Stream content ends
35 while (contentLen != 0)
36 {
37 // Write Content from the file stream to the
38 // FTP Upload Stream
39 strm.Write(buff, 0, contentLen);
40 contentLen = fs.Read(buff, 0, buffLength);
41 }
42 // Close the file stream and the Request Stream
43 strm.Close();
44 fs.Close();
45 }
46 catch(Exception ex)
47 {
48 MessageBox.Show(ex.Message, "Upload Error");
49 }
50 }
51


以上是FTP上传的代码事例。内在替代的使用命令是STOR,这里有一个FTPWEBREQUEST对象就是在FTP服务器上建立文件。为当前请求设置的不同属性是 验证,保持激活状态,二进制使用,内容长度。文件在本地机器打开后内容被写到了FTP请求的数据流中。这有一个2KB大小的缓冲区被使用用来作为一个合适的大小上传大文件和小文件

 


 1 private void Download(string filePath, string fileName)
 2 {
 3 FtpWebRequest reqFTP;
 4 try
 5 {
 6 //filePath = <<The full path where the
 7 //file is to be created. the>>,
 8 //fileName = <<Name of the file to be createdNeed not
 9 //name on FTP server. name name()>>
10 FileStream outputStream = new FileStream(filePath +
11 "\\" + fileName, FileMode.Create);
12 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" +
13 ftpServerIP + "/" + fileName));
14 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
15 reqFTP.UseBinary = true;
16 reqFTP.Credentials = new NetworkCredential(ftpUserID,
17 ftpPassword);
18 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
19 Stream ftpStream = response.GetResponseStream();
20 long cl = response.ContentLength;
21 int bufferSize = 2048;
22 int readCount;
23 byte[] buffer = new byte[bufferSize];
24 readCount = ftpStream.Read(buffer, 0, bufferSize);
25 while (readCount > 0)
26 {
27 outputStream.Write(buffer, 0, readCount);
28 readCount = ftpStream.Read(buffer, 0, bufferSize);
29 }
30 ftpStream.Close();
31 outputStream.Close();
32 response.Close();
33 }
34 catch (Exception ex)
35 {
36 MessageBox.Show(ex.Message);
37 }
38 }
39 
40 

以上是从FTP服务器上下载文件的例子代码。与上面描述的上传文件函数不一样的是,下载会要求接收文件流,包含着文件请求的大小。这里的文件下载较特殊的是创建TPWEBREQUEST对象时URI部分反过来使用。用“GET”去请求文件,使用FtpWebRequest对象的GetResponse()的方法接收。这个新的接收对象建立提供了包含文件内容数据流的接收数据流。你能够很容易的转化一个数据流为一个文件。

注意:我们可以灵活的设置保存在我们本地的文件的文件名和文件夹



 1 public string[] GetFileList()
 2 {
 3 string[] downloadFiles;
 4 StringBuilder result = new StringBuilder();
 5 FtpWebRequest reqFTP;
 6 try
 7 {
 8 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(
 9 "ftp://" + ftpServerIP + "/"));
10 reqFTP.UseBinary = true;
11 reqFTP.Credentials = new NetworkCredential(ftpUserID,
12 ftpPassword);
13 reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
14 WebResponse response = reqFTP.GetResponse();
15 StreamReader reader = new StreamReader(response
16 .GetResponseStream());
17 string line = reader.ReadLine();
18 while (line != null)
19 {
20 result.Append(line);
21 result.Append("\n");
22 line = reader.ReadLine();
23 }
24 // to remove the trailing '\n'
25 result.Remove(result.ToString().LastIndexOf('\n'), 1);
26 reader.Close();
27 response.Close();
28 return result.ToString().Split('\n');
29 }
30 catch (Exception ex)
31 {
32 System.Windows.Forms.MessageBox.Show(ex.Message);
33 downloadFiles = null;
34 return downloadFiles;
35 }
36 }
37 

以上是一个获得FTP服务器列表的例子,URI的建立是所要求的的地址和FTP服务器的地址和名称。在上面的例子里根文件夹被FtpWebRequest对象创建。这里接收的数据流是由StreamReader对象创建的,整个列表的名字在服务器上用“\r\n”分隔。你可以用StreamReader对象的ReadToEnd()方法获取整个列表(“\r\n”分隔)。以上的实例,每个文件名的读取是由一个StringBuilder对象把名字附加上的。结果是StringBuilder对象返回一个字符串数组。我确定这是一种很好的方式。一种更好的是可以从整个列表中去除‘\r’(返回一个《STREAMREADER.READTOEND())然后用’\n’分隔开。无论什么方式,我们不能去花费更多的资源和时间。

 

       上面的实例包含重命名,删除,获取文件大小,文件列表详情,建立目录都是非常熟悉且简单的代码片段。

注意:重名时,新的名字能够用FtpWebRequest对象的RenameTo属性标志,新目录的名字作为URI的一部分用来创建FtpWebRequest对象