前几天做个ftp下载小程序单位用,但是发现有时候文件下载不完整,我查了老半天才发现时因为网络延迟导致,解决方法是加个断线续传,爱我去,一开始我以为挺简单,做了两天参照网上的代码就是不行,才请各位老师们指点指点
if (a.ToString() != readCount.ToString())//断点续传
                {
                    Uri urii=new Uri("ftp://192.168.1.123:21");
                    FileInfo fileInfo = new FileInfo("E:\\报价\\巴比来定制产品.rar");
                    long locSize = fileInfo.Length;
                    RestartDownloadFromServer("巴比来定制产品.rar", urii, locSize);
                    CloseSocketConnect();
                    Socket soketData = CreateDataSocket();
                    Byte[] cmdType = GB2312.GetBytes(("TYPE I \r\n"));
                    socketControl.Send(cmdType, cmdType.Length, 0);                    MessageBox.Show("开始断点续传");
                    FileStream output = new
                    FileStream("E:\\报价\\" + "巴比来定制产品.rar", FileMode.Append, FileAccess.Write);
                    Byte[] cmdPASV = GB2312.GetBytes(("PASV \r\n").ToCharArray());
                    socketControl.Send(cmdPASV, cmdPASV.Length, 0);
                    //获取本地文长度
                    FileInfo fileInfo = new FileInfo("E:\\报价\\巴比来定制产品.rar");
                    long locSize = fileInfo.Length;
                    MessageBox.Show(locSize.ToString());                    //发送指令加文件长度
                    Byte[] cmdByte = GB2312.GetBytes(("REST " + locSize + " \r\n").ToCharArray());
                    socketControl.Send(cmdByte, cmdByte.Length, 0);
                    //发送指令加文件名和路径
                    Byte[] cmdRETR = GB2312.GetBytes(("RETR " + "E:\\报价\\巴比来定制产品.rar \r\n").ToCharArray());
                    socketControl.Send(cmdByte, cmdByte.Length, 0);
                    //下载.
                    int iBytes = 0;
                    int cnt = 0;
                    while (iBytes >= 0)
                    {
                        try
                        {
                            MessageBox.Show((cnt++).ToString());
                            iBytes = soketData.Receive(buffer, buffer.Length, 0);                            output.Write(buffer, 0, iBytes);
                            //if (iBytes <= 0)
                            //{
                            //    break;
                            //}
                        }
                        catch
                        {                        }                    }
                    output.Close();
}C#FTP断点续传winfrom网络

解决方案 »

  1.   

    忘记说了,我跟到while循环里执行了一次就停了,程序部走了,也没报错,也没有向流里写入
      

  2.   

    while的  iBytes >= 0 应该只会执行一次吧? 
    你把调改改成 >= 要处理的文件的总大小呢?
      

  3.   

    iBytes = soketData.Receive(buffer, buffer.Length, 0);发过来的数据都收完了,自然是等待接收新的数据了
    续传你就把块号和偏移量记下
      

  4.   

            // 从服务器上下载文件到本地事件
            private void btndownload_Click(object sender, EventArgs e)
            {
                 timer1.Start();
                 timer1.Stop();
                 DownLoad();
            }
            public void DownLoad()
            {
                string uri = null;
                int cntByte = 0;
                try
                {
                    uri = GetUriString(locFileName);
                    FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.DownloadFile);
                    FtpWebResponse response = GetFtpResponse(request);
                    if (response == null)
                    {
                        lstbxFtpState.Items.Add("服务器未响应...");
                        lstbxFtpState.TopIndex = lstbxFtpState.Items.Count - 1;
                        return;
                    }
                    Stream responseStream = response.GetResponseStream();
                    ms = new MemoryStream();
                    FileStream filestream = System.IO.File.Create(Path);
                    int readCount;
                    readCount = GetFtpFileSize();                int buflength = 1024 * 64;
                    byte[] buffer = new byte[buflength];
                    int bytesRead = 1;
                    lstbxFtpState.Items.Add("打开下载通道,文件下载中...");
                    
                    progressBar1.Maximum = readCount;
                    progressBar1.Value = 0;
                    while (bytesRead != 0 )
                    {       
                            bytesRead = responseStream.Read(buffer, 0, buflength);
                            filestream.Write(buffer, 0, bytesRead);
                            ms.Write(buffer, 0, bytesRead);
                            cntByte += bytesRead;
                            lstbxFtpState.Items.Add("已下载:" + cntByte.ToString());
                            lstbxFtpState.Items.Add("还剩:" + (readCount - cntByte).ToString());
                            lstbxFtpState.TopIndex = lstbxFtpState.Items.Count - 1;
                            progressBar1.Value = Convert.ToInt32(cntByte);
                            Application.DoEvents(); 
                    }
                    FileInfo file = new FileInfo(Path);
                    int locSize = Convert.ToInt32(file.Length);
                    if (locSize.ToString() != readCount.ToString())
                    {
                        filestream.Close();
                        WriteToRam(buffer, buffer.Length, uri, locSize,file);
                        lstbxFtpState.Items.Add("已下载:" + readCount);
                        lstbxFtpState.Items.Add("还剩:" + 0);
                        lstbxFtpState.TopIndex = lstbxFtpState.Items.Count - 1;
                        progressBar1.Value = Convert.ToInt32(cntByte);
                    }
                    MessageBox.Show(locFileName + "下载完成!");
                }
                catch (WebException ex)
                {
                    MessageBox.Show(ex.Message, "下载失败");
                }
            }
            MemoryStream ms = null;
            /// <summary>
            /// 断点续传
            /// </summary>
            /// <param name="buffer">缓冲池</param>
            /// <param name="buflength">缓冲长度</param>
            /// <param name="locSize">本地文件最大长度</param>
            /// <param name="locFile">本地文件对象</param>
            public void WriteToRam(byte[] buffer, int buflength,string uri,int locSize,FileInfo locFile)
            {
                FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.DownloadFile);
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                request.ContentOffset = locSize;
                FtpWebResponse response = null;
                response = (FtpWebResponse)request.GetResponse();
                Stream newFile = response.GetResponseStream();
                while (true)
                {
                    int readLen = newFile.Read(buffer, 0, buffer.Length);
                    if (readLen <= 0)
                    {
                        break;
                    }
                    ms.Write(buffer, 0, readLen);
                }
                newFile.Close();
              
                    ms.Position = 0;
                    if (locFile.Exists)
                    {
                        locFile.Delete();
                    }
                    using (FileStream fs = System.IO.File.Open(Path, FileMode.Create))
                    {
                        while (true)
                        {
                            int readLen = ms.Read(buffer, 0, buffer.Length);
                            if (readLen <= 0)
                            {
                                break;
                            }
                            fs.Write(buffer, 0, readLen);
                        }
                    }
                    ms.Close();
            }
            // 获得选择的文件
            // 如果选择的是目录或者是返回上层目录,则返回null
            private string GetSelectedFile()
            {
                string filename = string.Empty;
                if (!(lstbxFtpResources.SelectedIndex == -1 || lstbxFtpResources.SelectedItem.ToString().Substring(0, 4) == "[目录]"))
                {
                    string[] namefield = lstbxFtpResources.SelectedItem.ToString().Split(' ');
                    filename = namefield[0];
                }
                return filename;
            }
            #endregion
            // 变更目录操作
            private void lstbxFtpResources_DoubleClick(object sender, EventArgs e)
            {
                // 点击返回上层目录
                if (lstbxFtpResources.SelectedIndex == 0)
                {
                    if (currentDir == "/")
                    {
                        MessageBox.Show("当前目录已经是顶层目录", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return;
                    }
                    int index = currentDir.LastIndexOf("/");
                    if (index == 0)
                    {
                        currentDir = "/";
                    }
                    else
                    {
                        currentDir = currentDir.Substring(0, index);
                    }
                    // 每次更改目录后立即刷新资源列表
                    ShowFtpFileAndDirectory();
                }
                else
                {
                    if (lstbxFtpResources.SelectedIndex > 0 && lstbxFtpResources.SelectedItem.ToString().Contains("[目录]"))
                    {
                        if (currentDir == "/")
                        {
                            currentDir = "/" + lstbxFtpResources.SelectedItem.ToString().Substring(4);
                        }
                        else
                        {
                            currentDir = currentDir + "/" + lstbxFtpResources.SelectedItem.ToString().Substring(4);
                        }
                        string[] currentDirfield = currentDir.Split(' ');
                        currentDir = currentDirfield[0];
                        // 每次更改目录后立即刷新资源列表
                        ShowFtpFileAndDirectory();
                    }
                }
            }
            private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                e.Cancel = true; this.Hide(); 
                this.notifyIcon1.Visible = true;
            }           private void Form1_Load(object sender, EventArgs e)
            {
                LoadInformation();
            }
            public void LoadInformation()
            {
                lbl_FileAppend.Text =locFileName;
                WshShell shell = new WshShell();
                IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\" + "创建的文件夹快捷方式.lnk");
                try
                {  
                    if (ShowFtpFileAndDirectory() == true)
                    {
                        //btnlogin.Enabled = false;
                        btnlogout.Enabled = true;
                        lstbxFtpResources.Enabled = true;
                        lstbxFtpState.Enabled = true;
                        tbxServerIp.Enabled = false;
                        if (chkbxAnonymous.Checked == false)
                        {
                            tbxUsername.Enabled = false;
                            tbxPassword.Enabled = false;
                            chkbxAnonymous.Enabled = false;
                        }
                        else
                        {
                            chkbxAnonymous.Enabled = false;
                        }
                        Directory.CreateDirectory(@"D:\\路径");                    shortcut.TargetPath = "D:\\路径";
                        shortcut.Arguments = "-ano";
                        shortcut.WindowStyle = 1;
                        shortcut.Save();
                        tbxloginmessage.Text = "登录成功";
                        btndownload.Enabled = true;
                    }
                    else
                    {
                        lstbxFtpState.Enabled = true;
                        tbxloginmessage.Text = "登录失败";
                    }
                }
                catch (WebException ex)
                {
                    MessageBox.Show("远程服务器没有响应!", "确定");
                }
            }
            private int GetFtpFileSize()
            {
                FtpWebRequest reqFTP;
                int fileSize = 0;
                try
                {
                    reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp + 端口号" +locFileName));                reqFTP.Credentials = new NetworkCredential(userName, passWord);                reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;                reqFTP.UseBinary = true;
                    FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                    Stream ftpStream = response.GetResponseStream();
                    fileSize = (int)response.ContentLength;
                    ftpStream.Close();
                    response.Close();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                return fileSize;
            }
            private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                notifyIcon1.Visible  = false;
            }        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                Application.Exit();
            }    }
    }
      

  5.   

    //问题已经解决,我换了种做法, 把接收的文件放到内存里用了微软封装好的获取偏移量,下面代码实现了断点续传下载,但是代码有点杂乱,需要的自己整理一下吧
    using System;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Windows.Forms;
    using IWshRuntimeLibrary;
    using System.Data;
    namespace FTPUpDownloader
    {
        public partial class Form1 : Form
        {
            static string remoteIP = "FTP地址";
            static string userName = "用户名";
            static string passWord = "密码";
            static int port = 端口;
            static string locFileName = "文件名.rar";
            static string locPath = "D:\\文件路径\\";
            static string Path = locPath + locFileName;
            private string ftpUristring = "ftp+端口号";
            private NetworkCredential networkCredential;
            private string currentDir = "/";
            public Form1()
            {
                InitializeComponent();
                IPAddress[] ips = Dns.GetHostAddresses("");
                tbxServerIp.Text = ips[0].ToString();
                tbxServerIp.SelectAll();
                btnlogout.Enabled = false;
                lstbxFtpResources.Enabled = false;
                lstbxFtpState.Enabled = false;
            }
            #region 与服务器的交互
            private FtpWebRequest CreateFtpWebRequest(string uri, string requestMethod)
            {
                try
                {
                    FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(uri);
                    networkCredential = new NetworkCredential(userName,passWord);
                    request.Credentials = networkCredential;
                    request.KeepAlive = true;
                    request.UseBinary = true;
                    request.Method = requestMethod;
                    return request;
                }
                catch (WebException e)
                {
                    MessageBox.Show("端口无效!!" + e.Status);
                    return null;
                }
            }
            private FtpWebResponse GetFtpResponse(FtpWebRequest request)
            {
                FtpWebResponse response = null;
                try
                {
                    response = (FtpWebResponse)request.GetResponse();
                    lstbxFtpState.Items.Add("验证完毕,服务器回应信息:[" + response.WelcomeMessage + "]");
                    lstbxFtpState.Items.Add("正在连接:[ " + response.BannerMessage + "]");
                    lstbxFtpState.TopIndex = lstbxFtpState.Items.Count - 1;
                    return response;
                }
                catch (WebException ex)
                {
                    lstbxFtpState.Items.Add("发送错误。返回信息为:" + ex.Status);
                    lstbxFtpState.TopIndex = lstbxFtpState.Items.Count - 1;
                    return null;
                }
            }
            #endregion
            private bool ShowFtpFileAndDirectory()
            {
                lstbxFtpResources.Items.Clear();
                string uri = string.Empty;
                if (currentDir == "/")
                {
                    uri = ftpUristring;
                }
                else
                {
                    uri = ftpUristring + currentDir;
                }            string[] urifield = uri.Split(' ');
                uri = urifield[0];
                FtpWebRequest request = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.ListDirectoryDetails);            FtpWebResponse response = GetFtpResponse(request);
                if (response == null)
                {
                    return false;
                }
                lstbxFtpState.Items.Add("连接成功,服务器返回的是:" + response.StatusCode + " " + response.StatusDescription);
                Stream stream = response.GetResponseStream();
                StreamReader streamReader = new StreamReader(stream, Encoding.UTF8 );
                lstbxFtpState.Items.Add("获取响应流....");
                string s = streamReader.ReadToEnd();
                streamReader.Close();
                stream.Close();
                response.Close();
                lstbxFtpState.Items.Add("传输完成");
                string[] ftpdir = s.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                lstbxFtpResources.Items.Add("↑返回上层目录");
                int length = 0;
                for (int i = 0; i < ftpdir.Length; i++)
                {
                    if (ftpdir[i].EndsWith("."))
                    {
                        length = ftpdir[i].Length - 2;
                        break;
                    }
                }
                for (int i = 0; i < ftpdir.Length; i++)
                {
                    s = ftpdir[i];
                    int index = s.LastIndexOf('\t');
                    if (index == -1)
                    {
                        if (length < s.Length)
                        {
                            index = length;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    string name = s.Substring(index + 1);
                    if (name == "." || name == "..")
                    {
                        continue;
                    }
                    if (s[0] == 'd' || (s.ToLower()).Contains("<dir>"))
                    {
                        string[] namefield = name.Split(' ');
                        int namefieldlength = namefield.Length;
                        string dirname;
                        dirname = namefield[namefieldlength - 1];
                        dirname = dirname.PadRight(34, ' ');
                        name = dirname;                    lstbxFtpResources.Items.Add("[目录]" + name);
                    }
                }
                for (int i = 0; i < ftpdir.Length; i++)
                {
                    s = ftpdir[i];
                    int index = s.LastIndexOf('\t');
                    if (index == -1)
                    {
                        if (length < s.Length)
                        {
                            index = length;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    string name = s.Substring(index + 1);
                    if (name == "." || name == "..")
                    {
                        continue;
                    }
                    if (!(s[0] == 'd' || (s.ToLower()).Contains("<dir>")))
                    {
                        string[] namefield = name.Split(' ');
                        int namefieldlength = namefield.Length;
                        string filename;                    filename = namefield[namefieldlength - 1];
                        filename = filename.PadRight(34, ' ');
                        name = filename;
                        lstbxFtpResources.Items.Add(name);
                    }
                }
                return true;
            }
            #region 对文件的操作模块实现        private string GetUriString(string filename)
            {
                string uri = string.Empty;
                if (currentDir.EndsWith("/"))
                {
                    uri = ftpUristring + currentDir + filename;
                }
                else
                {
                    uri = ftpUristring + currentDir + "/" + filename;
                }            return uri;
            }
            public class Downloader
            {
                //委托
                public delegate void dDownloadProgress(long total, long current);
                //事件
                public event dDownloadProgress onDownLoadProgress;
                //开始模拟工作
                public void Start()
                {
                    for (int i = 0; i < 100; i++)
                    {
                        if (onDownLoadProgress != null)
                            onDownLoadProgress(100, i);
                        System.Threading.Thread.Sleep(100);
                    }
                }
            }        void downloader_onDownLoadProgress(long total, long current)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new Downloader.dDownloadProgress(downloader_onDownLoadProgress), new object[] { total, current });
                }
                else
                {
                    this.progressBar1.Maximum = (int)total;
                    this.progressBar1.Value = (int)current;
                }
            }
            private void change()
            {
                for (int i = 1; i <= 100; i++)
                {
                    progressBar1.PerformStep();
                    Application.DoEvents();
                }
            }