最近抄了书上的一个FTP的例子,上传和下载是可以了,但是,上传后的文件和下载下来的文件都不能打开,文本倒是可以打开,但是,汉字部分不显示,初学网络编程,希望大侠们指点一二。
例子如下//服务端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Globalization;namespace ftpServer
{
public partial class MainForm : Form
{
TcpListener myTcpListener;
Dictionary<string, string> users; public MainForm()
{
InitializeComponent(); users = new Dictionary<string, string>();
users.Add("mytestName", "123456");
txbDir.Text = "e:/ls/";
} //启动服务
private void btnFTPStart_Click(object sender, EventArgs e)
{
listBox1.Items.Add("FTP服务已启动");
Thread t = new Thread(ListenClientConnect);
t.Start();
btnFTPStart.Enabled = false;
btnStop.Enabled = true;
}
/// <summary>
/// 监听端口,处理客户端连接
/// </summary>
private void ListenClientConnect()
{
myTcpListener = new TcpListener(IPAddress.Any, 21);
myTcpListener.Start();
while (true)
{
try
{
TcpClient client = myTcpListener.AcceptTcpClient();
AddInfo(string.Format("{0}和本机{1}建立FTP连接",
client.Client.RemoteEndPoint, myTcpListener.LocalEndpoint));
User user = new User();
user.commandSession = new UserSession(client);
user.WorkDir = txbDir.Text;
Thread t = new Thread(userProcessing);
t.IsBackground = true;
t.Start(user);
}
catch
{ break; }
}
}
/// <summary>
/// 客户连接
/// </summary>
/// <param name="user"></param>
private void userProcessing(object obj)
{
User user = (User)obj;
string sendString = "220 FTP Server V1.0";
string oldFileName = "";
ReplyCommandToUser(user, sendString);
while (true)
{
string ReceiveString = null;
try
{
ReceiveString = user.commandSession.sr.ReadLine();
}
catch
{
if (user.commandSession.client.Connected == false)
{
AddInfo("客户端断开连接");
}
else
{
AddInfo("命令接收失败");
}
break;
}
if (ReceiveString == null)
{
AddInfo("接收字符为null,线程结束");
break;
} AddInfo(string.Format("来自[{0}]--{1}", user.commandSession.client.Client.RemoteEndPoint, ReceiveString)); //分解客户端发过来的控制信息中的命令及参数
string command = ReceiveString;
string param = string.Empty;
int index = ReceiveString.IndexOf(' ');
if (index != -1)
{
command = ReceiveString.Substring(0, index).ToUpper();
param = ReceiveString.Substring(command.Length).Trim();
}
//处理不需要登录即可响应的命令(此处仅处理QUIT)
if (command == "QUIT")
{
//关闭TCP连接并释放与其相关的所有资源
user.commandSession.close();
return;
}
else
{
switch (user.loginOK)
{
//等待用户输入用户名
case 0:
CommandUser(user, command, param);
break;
//等待用户输入密码
case 1:
CommandPassword(user, command, param);
break;
//用户名和密码正确时登录
case 2:
{
switch (command)
{
case "CWD":
CommandCWD(user, param);
break;
case "PWD":
CommandPWD(user);//显示工作目录
break;
case "PASV":
CommandPASV(user);
break;
case "PORT":
CommandPORT(user, param);
break;
case "LIST":
case "NLIST":
CommandLIST(user, param);//显示目录和文件
break;
case "RETR":
CommandRETR(user, param);
break;
case "STOR":
CommandSTOR(user, param);
break;
case "TYPE":
CommandTYPE(user, param);
break;
default:
sendString = "502 command is not implemented.";
ReplyCommandToUser(user, sendString);
break;
}
}
break;
}
} }
}
/// <summary>
/// 处理USER命令,但不进行用户验证
/// </summary>
/// <param name="user"></param>
/// <param name="command"></param>
/// <param name="param"></param>
private void CommandUser(User user, string command, string param)
{
string sendString = string.Empty;
if (command == "USER")
{
sendString = "331 USER command OK,password required.";
user.userName = param;
user.loginOK = 1;//表示已接收到用户名,等待接收密码
}
else
{
sendString = "501 USER command syntax error.";
}
ReplyCommandToUser(user, sendString);
} /// <summary>
/// 输入密码
/// </summary>
/// <param name="user"></param>
/// <param name="command"></param>
/// <param name="param"></param>
private void CommandPassword(User user, string command, string param)
{
string sendString = string.Empty;
if (command == "PASS")
{
string password = null;
if (users.TryGetValue(user.userName, out password))
{
if (password == param)
{
sendString = "230 User logged in success";
user.loginOK = 2; //2表示登录成功
}
else
sendString = "530 Password incorrect.";
}
else
{
sendString = "530 User name or password incorrect.";
}
}
else
{
sendString = "530 PASS command Syntax error.";
}
ReplyCommandToUser(user, sendString);
user.CurrentDir = user.WorkDir;
} /// <summary>
/// 处理CWD命令,改变工作目录
/// </summary>
/// <param name="user"></param>
/// <param name="temp"></param>
private void CommandCWD(User user, string temp)
{
string sendString = string.Empty;
try
{
string dir = user.WorkDir.TrimEnd('/') + temp;
//是当前目录的子目录,且不包含父目录名称
if (Directory.Exists(dir))
{
user.CurrentDir = dir;
sendString = "250 Directory changed to '" + dir + "' successfully.";
}
else
{
sendString = "550 Directory '" + dir + "' does not exist.";
}
}
catch
{
sendString = "502 Directory changed unsuccessfully.";
}
ReplyCommandToUser(user, sendString);
}
例子如下//服务端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Globalization;namespace ftpServer
{
public partial class MainForm : Form
{
TcpListener myTcpListener;
Dictionary<string, string> users; public MainForm()
{
InitializeComponent(); users = new Dictionary<string, string>();
users.Add("mytestName", "123456");
txbDir.Text = "e:/ls/";
} //启动服务
private void btnFTPStart_Click(object sender, EventArgs e)
{
listBox1.Items.Add("FTP服务已启动");
Thread t = new Thread(ListenClientConnect);
t.Start();
btnFTPStart.Enabled = false;
btnStop.Enabled = true;
}
/// <summary>
/// 监听端口,处理客户端连接
/// </summary>
private void ListenClientConnect()
{
myTcpListener = new TcpListener(IPAddress.Any, 21);
myTcpListener.Start();
while (true)
{
try
{
TcpClient client = myTcpListener.AcceptTcpClient();
AddInfo(string.Format("{0}和本机{1}建立FTP连接",
client.Client.RemoteEndPoint, myTcpListener.LocalEndpoint));
User user = new User();
user.commandSession = new UserSession(client);
user.WorkDir = txbDir.Text;
Thread t = new Thread(userProcessing);
t.IsBackground = true;
t.Start(user);
}
catch
{ break; }
}
}
/// <summary>
/// 客户连接
/// </summary>
/// <param name="user"></param>
private void userProcessing(object obj)
{
User user = (User)obj;
string sendString = "220 FTP Server V1.0";
string oldFileName = "";
ReplyCommandToUser(user, sendString);
while (true)
{
string ReceiveString = null;
try
{
ReceiveString = user.commandSession.sr.ReadLine();
}
catch
{
if (user.commandSession.client.Connected == false)
{
AddInfo("客户端断开连接");
}
else
{
AddInfo("命令接收失败");
}
break;
}
if (ReceiveString == null)
{
AddInfo("接收字符为null,线程结束");
break;
} AddInfo(string.Format("来自[{0}]--{1}", user.commandSession.client.Client.RemoteEndPoint, ReceiveString)); //分解客户端发过来的控制信息中的命令及参数
string command = ReceiveString;
string param = string.Empty;
int index = ReceiveString.IndexOf(' ');
if (index != -1)
{
command = ReceiveString.Substring(0, index).ToUpper();
param = ReceiveString.Substring(command.Length).Trim();
}
//处理不需要登录即可响应的命令(此处仅处理QUIT)
if (command == "QUIT")
{
//关闭TCP连接并释放与其相关的所有资源
user.commandSession.close();
return;
}
else
{
switch (user.loginOK)
{
//等待用户输入用户名
case 0:
CommandUser(user, command, param);
break;
//等待用户输入密码
case 1:
CommandPassword(user, command, param);
break;
//用户名和密码正确时登录
case 2:
{
switch (command)
{
case "CWD":
CommandCWD(user, param);
break;
case "PWD":
CommandPWD(user);//显示工作目录
break;
case "PASV":
CommandPASV(user);
break;
case "PORT":
CommandPORT(user, param);
break;
case "LIST":
case "NLIST":
CommandLIST(user, param);//显示目录和文件
break;
case "RETR":
CommandRETR(user, param);
break;
case "STOR":
CommandSTOR(user, param);
break;
case "TYPE":
CommandTYPE(user, param);
break;
default:
sendString = "502 command is not implemented.";
ReplyCommandToUser(user, sendString);
break;
}
}
break;
}
} }
}
/// <summary>
/// 处理USER命令,但不进行用户验证
/// </summary>
/// <param name="user"></param>
/// <param name="command"></param>
/// <param name="param"></param>
private void CommandUser(User user, string command, string param)
{
string sendString = string.Empty;
if (command == "USER")
{
sendString = "331 USER command OK,password required.";
user.userName = param;
user.loginOK = 1;//表示已接收到用户名,等待接收密码
}
else
{
sendString = "501 USER command syntax error.";
}
ReplyCommandToUser(user, sendString);
} /// <summary>
/// 输入密码
/// </summary>
/// <param name="user"></param>
/// <param name="command"></param>
/// <param name="param"></param>
private void CommandPassword(User user, string command, string param)
{
string sendString = string.Empty;
if (command == "PASS")
{
string password = null;
if (users.TryGetValue(user.userName, out password))
{
if (password == param)
{
sendString = "230 User logged in success";
user.loginOK = 2; //2表示登录成功
}
else
sendString = "530 Password incorrect.";
}
else
{
sendString = "530 User name or password incorrect.";
}
}
else
{
sendString = "530 PASS command Syntax error.";
}
ReplyCommandToUser(user, sendString);
user.CurrentDir = user.WorkDir;
} /// <summary>
/// 处理CWD命令,改变工作目录
/// </summary>
/// <param name="user"></param>
/// <param name="temp"></param>
private void CommandCWD(User user, string temp)
{
string sendString = string.Empty;
try
{
string dir = user.WorkDir.TrimEnd('/') + temp;
//是当前目录的子目录,且不包含父目录名称
if (Directory.Exists(dir))
{
user.CurrentDir = dir;
sendString = "250 Directory changed to '" + dir + "' successfully.";
}
else
{
sendString = "550 Directory '" + dir + "' does not exist.";
}
}
catch
{
sendString = "502 Directory changed unsuccessfully.";
}
ReplyCommandToUser(user, sendString);
}
private void CommandRETR(User user, string fileName)
{
string sendString = "";
//下载文件的全名
string path = user.CurrentDir + fileName;
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
//发送150到用户,意思为服务器状态良好
if (user.isBinary)
{
sendString = "150 Opening BINARY mode data connection for dowload";
}
else
{
sendString = "150 Opening ASCII mode data connection for dowload.";
}
ReplyCommandToUser(user, sendString);
iniDataSession(user);
SendFileByUsersession(user, fs);
ReplyCommandToUser(user, "226 Transfer complete.");
} /// <summary>
/// 处理STOR命令,提供上传功能,接收用户上传的文件
/// </summary>
/// <param name="user"></param>
/// <param name="fileName"></param>
private void CommandSTOR(User user, string fileName)
{
string sendString = "";
string path = user.CurrentDir + fileName;
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
//发送150到用户,表示服务器状态良好
if (user.isBinary)
{
sendString = "150 Opening BINARY mode data connection for upload";
}
else
{
sendString = "150 Opening ASCII mode data connection for upload";
}
ReplyCommandToUser(user, sendString);
iniDataSession(user);
ReadFileBySession(user, fs);
ReplyCommandToUser(user, "226 Tansfer complete.");
} /// <summary>
/// 初始化数据连接
/// </summary>
/// <param name="user"></param>
private void iniDataSession(User user)
{
TcpClient client = null;
if (user.isPassive)
{
AddInfo("采用被动模式返回LIST命令结果");
client = user.dataListener.AcceptTcpClient();
}
else
{
AddInfo("采用主动模式向用户发送LIST结果");
client = new TcpClient();
client.Connect(user.remoteEndPoint);
}
user.isBinary = true;
user.dataSession = new UserSession(client);
} /// <summary>
/// 使用数据连接发送字符串数据
/// </summary>
/// <param name="user"></param>
/// <param name="sendString"></param>
private void SendByUserSession(User user, string sendString)
{
AddInfo("开始向用户发送:" + sendString);
try
{
user.dataSession.sw.WriteLine(sendString);
AddInfo("发送完毕");
}
finally
{ user.dataSession.close(); }
} /// <summary>
/// 使用数据连接接收数据流
/// </summary>
/// <param name="user"></param>
/// <param name="fs"></param>
private void ReadFileBySession(User user, FileStream fs)
{
AddInfo("开始接收");
try
{
if (user.isBinary)
{
byte[] bytes = new byte[1024];
BinaryWriter bw = new BinaryWriter(fs);
int count = user.dataSession.br.Read(bytes, 0, bytes.Length);
while (count > 0)
{
bw.Write(bytes, 0, count);
count = user.dataSession.br.Read(bytes, 0, bytes.Length);
}
}
else
{
StreamWriter sw = new StreamWriter(fs);
while (user.dataSession.sr.Peek() > -1)
{
sw.WriteLine(user.dataSession.sr.ReadLine());
sw.Flush();
}
}
AddInfo("接收完毕");
}
finally
{
user.dataSession.close();
fs.Close();
}
} /// <summary>
/// 使用数据连接发送数据流
/// </summary>
/// <param name="user"></param>
/// <param name="fs"></param>
private void SendFileByUsersession(User user, FileStream fs)
{
AddInfo("开始发送文件流");
try
{
if (user.isBinary)
{
byte[] bytes = new byte[1024];
BinaryReader br = new BinaryReader(fs);
int count = br.Read(bytes, 0, bytes.Length);
while (count > 0)
{
user.dataSession.bw.Write(bytes, 0, count);
user.dataSession.bw.Flush();
count = br.Read(bytes, 0, bytes.Length);
}
}
else
{
StreamReader sr = new StreamReader(fs);
while (sr.Peek() > -1)
{
user.dataSession.sw.WriteLine(sr.ReadLine());
}
}
AddInfo("发送完毕");
}
finally
{
user.dataSession.close();
fs.Close();
}
} /// <summary>
/// 给用户发送信息
/// </summary>
/// <param name="user"></param>
/// <param name="sendstr"></param>
private void ReplyCommandToUser(User user, string sendstr)
{
try
{
user.commandSession.sw.WriteLine(sendstr);
AddInfo(string.Format("向{0}发送:{1}",
user.commandSession.client.Client.RemoteEndPoint, sendstr));
}
catch
{
AddInfo(string.Format("向{0}发送信息失败",
user.commandSession.client.Client.RemoteEndPoint));
}
} private delegate void AddInfoDelegate(string str);
/// <summary>
/// 添加信息
/// </summary>
/// <param name="str"></param>
private void AddInfo(string str)
{
if (listBox1.InvokeRequired)
{
AddInfoDelegate d = AddInfo;
listBox1.Invoke(d, str);
}
else
{
listBox1.Items.Add(str);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
listBox1.ClearSelected();
}
} //停止服务
private void btnStop_Click(object sender, EventArgs e)
{
myTcpListener.Stop();
AddInfo("FTP服务已停止");
this.Close();
}
}
//客户端
namespace FTPClient
{
public partial class Form1 : Form
{
private const int port = 21;//控制连接服务器的端口
private string ftpUriString;//要访问的资源
private NetworkCredential networkCredential;//身份验证信息
private string CurrentDir = "/";//客户端当前工作目录
public Form1()
{
InitializeComponent();
IPAddress[] ips = Dns.GetHostAddresses("");
txbServer.Text = ips[0].ToString();
txbUserName.Text = "mytestName";
txbPWD.Text = "123456";
}
/// <summary>
/// //从服务器获取指定路径下的文件及目录列表,并显示
private bool ShowFtpFileAndDirectory()
{
lsbFileList.Items.Clear();
string uri = string.Empty;
if (CurrentDir == "/")
{
uri = ftpUriString;
}
else
{ uri = ftpUriString + CurrentDir; } FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.ListDirectoryDetails);
//获取服务器响应
FtpWebResponse response = GetFtpWebResponse(request);
if (response == null)
return false;
lsbServerMSG.Items.Add("服务器返回:" + response.StatusDescription);
//读取网络流信息
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default);
string s = sr.ReadToEnd();
string[] ftpDir = s.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
//显示服务器显示的原信息
lsbServerMSG.Items.AddRange(ftpDir);
lsbServerMSG.Items.Add("服务器返回:" + response.StatusDescription);
//添加单击能返回上一层目录的项
lsbFileList.Items.Add("返回上层目录");
int len = 0;
for (int i = 0; i < ftpDir.Length; i++)
{
if (ftpDir[i].EndsWith("."))
{
len = ftpDir[i].Length - 2;
break;
}
} for (int i = 0; i < ftpDir.Length; i++)
{
s = ftpDir[i];
int indext = s.LastIndexOf('\t');
if (indext == -1)
{
if (len < s.Length)
{
indext = len;
}
else
continue;
}
string name = s.Substring(indext + 1);
if (name == "." || name == "..")
{
continue;
}
//判断是否为目录,在项前进行表示
if (s[0] == 'd' || (s.ToLower()).Contains("<dir>"))
{
lsbFileList.Items.Add("[目录]" + name);
}
}
for (int i = 0; i < ftpDir.Length; i++)
{
s = ftpDir[i];
int indext = s.LastIndexOf('\t');
if (indext == -1)
{
if (len < s.Length)
{ indext = len; }
else
continue;
}
string name = s.Substring(indext + 1);
if (name == "." || name == "..")
continue; if (!(s[0] == 'd' || (s.ToLower()).Contains("<dir>")))
{
lsbFileList.Items.Add("[文件]" + name);
}
}
return true; }
/// 创建FtpWebRequest对象
private FtpWebRequest CreateFtpWebRequest(string uri, string requestMethod)
{
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(uri);
request.Credentials = networkCredential;
request.KeepAlive = true;
request.UseBinary = true;
request.Method = requestMethod;
return request;
}
/// <summary>
/// 获得服务器响应信息
private FtpWebResponse GetFtpWebResponse(FtpWebRequest request)
{
FtpWebResponse response = null;
try
{
response = (FtpWebResponse)request.GetResponse();
return response;
}
catch (WebException err)
{
lsbServerMSG.Items.Add("出现异常,FTP返回状态:" + err.Status.ToString());
FtpWebResponse e = (FtpWebResponse)err.Response;
lsbServerMSG.Items.Add("status code :" + e.StatusCode);
lsbServerMSG.Items.Add("status Description :" + e.StatusDescription);
return null;
}
catch (Exception err)
{
lsbServerMSG.Items.Add(err.Message);
return null;
}
}
/// <summary>
/// 上传文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnUpload_Click(object sender, EventArgs e)
{
//上传文件
OpenFileDialog f = new OpenFileDialog();
if (f.ShowDialog() != DialogResult.OK)
{ return; }
FileInfo fileinfo = new FileInfo(f.FileName);
string uri = GetUriString(fileinfo.Name);
FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.UploadFile);
request.ContentLength = fileinfo.Length;
int buffLength = 1024;//缓存
byte[] buff = new byte[buffLength];
FileStream fs = fileinfo.OpenRead();
try
{
Stream responseStream = request.GetRequestStream();
int contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
responseStream.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
responseStream.Close();
fs.Close();
FtpWebResponse response = GetFtpWebResponse(request);
if (response == null)
{ return; }
ShowFtpFileAndDirectory();
}
catch (Exception err)
{
MessageBox.Show(err.Message, "上传失败");
}
} private string GetUriString(string filename)
{
string uri = string.Empty;
if (CurrentDir.EndsWith("/"))
{
uri = ftpUriString + CurrentDir + filename;
}
else
{
uri = ftpUriString + CurrentDir + "/" + filename;
}
return uri;
}
private string GetSelectedfile()
{
string fileName = "";
if (!(lsbFileList.SelectedIndex == -1 ||
lsbFileList.SelectedItem.ToString().Substring(0, 4) == "[目录]"))
{
fileName = lsbFileList.SelectedItem.ToString().Substring(4).Trim();
}
return fileName;
}
/// <summary>
/// <summary>
/// 下载文件
private void btnDownLoad_Click(object sender, EventArgs e)
{
string fileName = GetSelectedfile();
if (fileName.Length == 0)
{
MessageBox.Show("请选择要下载的文件");
return;
}
string filepath = Application.StartupPath + "\\DownLoad";
if (Directory.Exists(filepath) == false)
{
Directory.CreateDirectory(filepath);
}
Stream responseStream = null;
FileStream fileStream = null;
StreamReader reader = null;
try
{
string uri = GetUriString(fileName);
FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.DownloadFile);
FtpWebResponse response = GetFtpWebResponse(request);
if (response == null)
{ return; }
responseStream = response.GetResponseStream();
string path = filepath + "\\" + fileName;
fileStream = File.Create(path);
byte[] buffer = new byte[1024];
int bytesRead;
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
while (true)
{
bytesRead = responseStream.Read(buffer, 0, buffer.Length);
if (bytesRead == 0)
{ break; }
fileStream.Write(buffer, 0, bytesRead);
}
MessageBox.Show("下载完毕!");
}
catch (UriFormatException err)
{
MessageBox.Show(err.Message);
}
catch (WebException err)
{
MessageBox.Show(err.Message);
}
catch (IOException err)
{
MessageBox.Show(err.Message);
}
finally
{
if (reader != null)
{ reader.Close(); }
else if (responseStream != null)
{ responseStream.Close(); }
if (fileStream != null)
{ fileStream.Close(); }
}
}
}
}
byte[] responseArray = myWebClient.UploadFile(服务器路径,fileName);]WebClient client = new WebClient();
client.Headers.Add(HttpRequestHeader.Referer, "");
client.DownloadFile("", "");
ftp 操作