最近抄了书上的一个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);
        }      

解决方案 »

  1.   


             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();
            }
        }
      

  2.   


    //客户端
    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(); }
                }
            }       
        }
    }
      

  3.   

    WebClient myWebClient = new WebClient();
    byte[] responseArray = myWebClient.UploadFile(服务器路径,fileName);]WebClient client = new WebClient();
    client.Headers.Add(HttpRequestHeader.Referer, "");
    client.DownloadFile("", "");
    ftp 操作