我用C#实现FTP功能,已经可以上传下载了,但是有不稳定,当远程FTP服务器的数据量大或网速慢的时候下一会儿就提示如下错误:
   1、“基础连接断开,超时”,
   2、用户代码未处理 System.Net.WebException   Message="远程服务器返回错误: (500) 语法错  误,无法识别命令。"
请问用API是不是要稳定点,我的下载代码如下:
BackgroundWorker bw = sender as BackgroundWorker;
FtpSettings f = e.Argument as FtpSettings;IList<string> vDownFiles =new  List<string>();
string[] temp = GetFileList(f.Host ,f.Port , f.Username , f.Password ,f.TargetFolder , "*.*");
for (int i = 0; i < temp.Length; i++)
{
   vDownFiles.Add(temp[i]);
}foreach (string item in vDownFiles)
{
                if (item.Contains("win2003Hp.iso"))
                {
                    int kk = 10;
                }                FileStream outputStream = new FileStream(@"e:\test\" + item, FileMode.Create);                // set up the host string to request.  this includes the target folder and the target file name (based on the source filename)
                string DownLoadPath = String.Format("{0}/{1}{2}", f.Host, f.TargetFolder == "" ? "" : f.TargetFolder + "/", Path.GetFileName(item));
                if (!DownLoadPath.ToLower().StartsWith("ftp://"))
                    DownLoadPath = "ftp://" + DownLoadPath;
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(DownLoadPath);
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                request.UseBinary = true;
                request.UsePassive = f.Passive;
                request.Credentials = new NetworkCredential(f.Username, f.Password);                FtpWebResponse response = (FtpWebResponse)request.GetResponse();                Stream ftpStream = response.GetResponseStream();
                long cl = response.ContentLength;
                string FileSizeDescription = GetFileSize(cl);
                //int bufferSize = 2048;
                int readCount;
                long DownLoadBytes = 0;
                int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
                byte[] buffer = new byte[ChunkSize];                readCount = ftpStream.Read(buffer, 0, ChunkSize);
                while (readCount > 0)
                {                    //outputStream.Write(buffer, 0, readCount);
                    //readCount = ftpStream.Read(buffer, 0, bufferSize);                    //DownLoadBytes += readCount;                    //// update the user interface
                    //string SummaryText = String.Format("传输完成比率 {0} / {1}", GetFileSize(DownLoadBytes), FileSizeDescription);
                    //bw.ReportProgress((int)(((decimal)DownLoadBytes / (decimal)cl ) * 100), SummaryText);
                    try
                    {
                        if (bw.CancellationPending)
                            return;                        // send this chunk to the server.  it is sent as a byte[] parameter, but the client and server have been configured to encode byte[] using MTOM. 
                        outputStream.Write(buffer, 0, readCount);                        // sentBytes is only updated AFTER a successful send of the bytes. so it would be possible to build in 'retry' code, to resume the upload from the current SentBytes position if AppendChunk fails.
                        DownLoadBytes += readCount;                        // update the user interface
                        string SummaryText = String.Format("传输完成比率 {0} / {1}", GetFileSize(DownLoadBytes), FileSizeDescription);
                        bw.ReportProgress((int)(((double)DownLoadBytes / (double)cl) * 100), SummaryText);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Exception: " + ex.ToString());
                        if (NumRetries++ < MaxRetries)
                        {
                            // rewind the filestream and keep trying
                            ftpStream.Position -= DownLoadBytes;
                        }
                        else
                        {
                            throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
                        }
                    }
                    readCount = ftpStream.Read(buffer, 0, ChunkSize); // read the next chunk (if it exists) into the buffer.  the while loop will terminate if there is nothing left to read                }                ftpStream.Close();
                outputStream.Close();
                response.Close();
                using (FtpWebResponse responseN = (FtpWebResponse)request.GetResponse())
                    System.Diagnostics.Debug.WriteLine(String.Format("DownLoad File Complete, status {0}", responseN.StatusDescription));}

解决方案 »

  1.   

    如果服务器支持,可以使用端点续传增加可靠性。Google: ftpwebrequest 端点续传
      

  2.   

    首先非常感谢楼上的朋友,但是不够详细,最好有先关的DEMO或关键代码 
      

  3.   

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    Stream ftpStream = response.GetResponseStream();
    这两句放到try里面去
    internal static bool FtpDownloadFile(FtpSite ftpSite) //定义个对象,封装参数
            {
                if (ftpSite == null)
                {
                    throw new ArgumentNullException("ftpSite");
                }
                //根据URI创建FtpWebRequest对象
                FtpWebRequest ftpRequest = (FtpWebRequest)FtpWebRequest.Create(ftp.FileUri);
                //ftp用户名和密码
                ftpRequest.Credentials = new NetworkCredential(ftpSite.UserName, ftpSite.Password);
                ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;     //指定操作类别
                ftpRequest.UseBinary = true;    //指定数据传输类型
                ftpRequest.KeepAlive = false;   //下载完后不用保持连接
                return SaveAsFile(ftpRequest, upgradeReport.SaveFileName);
            }        /// <summary>
            /// 将服务端响应流保存至文件
            /// </summary>
            static bool SaveAsFile(WebRequest request, string saveName)
            {
                WebResponse response = null;
                request.Proxy = null;
                request.Timeout = 60000;    //设置请求超时时间
                //request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
                try
                {
                    response = (WebResponse)request.GetResponse();
                    using (var responseStream = response.GetResponseStream())
                    {
                        using (var fs = new FileStream(saveName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
                        {
                            int bufferLength = 2048, offset = 0;
                            byte[] buffer = new byte[bufferLength];
                            while ((offset = responseStream.Read(buffer, 0, bufferLength)) > 0)
                            {
                                fs.Write(buffer, 0, offset);
                            }                        
                        }
                    }
                    return true;
                }
                catch (Exception exp)
                {
                    //handle exp or throw;
                    return false;
                }
                finally
                {
                    if (response != null) response.Close();
                }
            }
      

  4.   

    我现在改成如下代码,可以下载的大小比原来提高很多,可是在下载一会儿就提示:远程服务器返回错误: (426) 连接关闭;传输中止。我的代码如下:
        FileStream outputStream = new FileStream(@"e:\test\" + item, FileMode.Create);                // set up the host string to request.  this includes the target folder and the target file name (based on the source filename)
                    string DownLoadPath = String.Format("{0}/{1}{2}", f.Host, f.TargetFolder == "" ? "" : f.TargetFolder + "/", Path.GetFileName(item));
                    if (!DownLoadPath.ToLower().StartsWith("ftp://"))
                        DownLoadPath = "ftp://" + DownLoadPath;
                    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(DownLoadPath);
                    request.Method = WebRequestMethods.Ftp.DownloadFile;
                    request.UseBinary = true;
                    request.UsePassive = f.Passive;
                    request.Credentials = new NetworkCredential(f.Username, f.Password);
                    request.KeepAlive = true;
                    request.ReadWriteTimeout = System.Threading.Timeout.Infinite;
                    request.Timeout = System.Threading.Timeout.Infinite;
                    request.Proxy = null;
                    request.UsePassive = false;                                             FtpWebResponse response = (FtpWebResponse)request.GetResponse();                Stream ftpStream = response.GetResponseStream();
                    long cl = response.ContentLength;
                    string FileSizeDescription = GetFileSize(cl);
                    //int bufferSize = 2048;
                    int readCount;
                    long DownLoadBytes = 0;
                    int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
                    byte[] buffer = new byte[ChunkSize];                readCount = ftpStream.Read(buffer, 0, ChunkSize);
                    while (readCount > 0)
                    {                    //outputStream.Write(buffer, 0, readCount);
                        //readCount = ftpStream.Read(buffer, 0, bufferSize);                    //DownLoadBytes += readCount;                    //// update the user interface
                        //string SummaryText = String.Format("传输完成比率 {0} / {1}", GetFileSize(DownLoadBytes), FileSizeDescription);
                        //bw.ReportProgress((int)(((decimal)DownLoadBytes / (decimal)cl ) * 100), SummaryText);
                        try
                        {
                            if (bw.CancellationPending)
                                return;                        // send this chunk to the server.  it is sent as a byte[] parameter, but the client and server have been configured to encode byte[] using MTOM. 
                            outputStream.Write(buffer, 0, readCount);                        // sentBytes is only updated AFTER a successful send of the bytes. so it would be possible to build in 'retry' code, to resume the upload from the current SentBytes position if AppendChunk fails.
                            DownLoadBytes += readCount;                        // update the user interface
                            string SummaryText = String.Format("传输完成比率 {0} / {1}", GetFileSize(DownLoadBytes), FileSizeDescription);
                            bw.ReportProgress((int)(((double)DownLoadBytes / (double)cl) * 100), SummaryText);
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine("Exception: " + ex.ToString());
                            if (NumRetries++ < MaxRetries)
                            {
                                // rewind the filestream and keep trying
                                ftpStream.Position -= DownLoadBytes;
                            }
                            else
                            {
                                throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
                            }
                        }
                        readCount = ftpStream.Read(buffer, 0, ChunkSize); // read the next chunk (if it exists) into the buffer.  the while loop will terminate if there is nothing left to read                }                ftpStream.Close();
                    outputStream.Close();
                    response.Close();
                    using (FtpWebResponse responseN = (FtpWebResponse)request.GetResponse())
                        System.Diagnostics.Debug.WriteLine(String.Format("DownLoad File Complete, status {0}", responseN.StatusDescription));            }
      

  5.   

    你可以用 http 协议 进行处理。
      

  6.   

    那个协议处理无所谓,关键是需要稳定,http协议是不是要稳定些
      

  7.   

    FtpWebRequest 好像是有这样那样的问题,还是用 socket 写把
      

  8.   

    自己搞定了代码贴出来供大家参考: /// <summary>
     /// 下载
     /// </summary>
     /// <param name="filePath"></param>
     /// <param name="fileName"></param>
    public void Download(string ftpURI, string fPath, string ftpUserID, string ftpPassword, string filePath)
            {           
                this.toolStripProgressBar1.Value = 0;
                using (BackgroundWorker backgroundWorker = new BackgroundWorker())
                {                
                    backgroundWorker.WorkerReportsProgress = true;
                    backgroundWorker.WorkerSupportsCancellation = true;
                    // 异步获取数据
                    backgroundWorker.DoWork += new DoWorkEventHandler(delegate(object o, DoWorkEventArgs workerEventArgs)
                    {
                        string[] temp = GetFileList(ftpURI, 21, ftpUserID, ftpPassword, fPath, "*.*");                    foreach (string item in temp)
                        {
                            string fileName = item;                        ifComplete = false;                        this.BeginInvoke(new myDelegatDoProcess(doProcess));                        //backgroundWorker.ReportProgress((int)(((double)0.1 / (double)1) * 100), "正在获得文件列表,请稍候..."); System.Threading.Thread.Sleep(1000);                        FtpWebRequest reqFTP;
                            try
                            {
                                //backgroundWorker.ReportProgress((int)(((double)0.75 / (double)1) * 100), "正在下载文件,请稍候..."); System.Threading.Thread.Sleep(1000);                            FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);                            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("Ftp://" + ftpURI + "/" + fPath + "/" + fileName));
                                reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
                                reqFTP.UseBinary = true;
                                reqFTP.UsePassive = false;
                                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                                Stream ftpStream = response.GetResponseStream();
                                long cl = response.ContentLength;
                                int bufferSize = 2048;
                                int readCount;
                                byte[] buffer = new byte[bufferSize];
                                long DownLoadBytes = 0;
                                string FileSizeDescription = GetFileSize(cl);
                                readCount = ftpStream.Read(buffer, 0, bufferSize);
                                while (readCount > 0)
                                {
                                    outputStream.Write(buffer, 0, readCount);
                                    readCount = ftpStream.Read(buffer, 0, bufferSize);                                DownLoadBytes += readCount;
                                    //this.Text = "文件[" + fileName + "]下载完成" + GetFileSize(DownLoadBytes) + @"/" + FileSizeDescription;
                                    //this.Refresh();
                                    string SummaryText = String.Format("正在下载文件 {0} 传输完成比率 {1} / {2}",item , GetFileSize(DownLoadBytes), FileSizeDescription);
                                    backgroundWorker.ReportProgress((int)(((double)DownLoadBytes / (double)cl) * 100), SummaryText);
                                    //this.Refresh();
                                    //statusStrip1.Refresh(); 
                                }                            ftpStream.Close();
                                outputStream.Close();
                                response.Close();
                            }
                            catch (Exception ex)
                            {
                                //Insert_Standard_ErrorLog.Insert("FtpWeb", "Download Error --> " + ex.Message);
                            }
                        }                    
                    });                backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(delegate(object sender, ProgressChangedEventArgs e)
                    {
                        //if (e.UserState != null && e.UserState.ToString() != "") { m_Result = e.UserState.ToString(); }
                        this.toolStripStatusLabel1.Text = e.UserState.ToString(); // the message will be something like: 45 Kb / 102.12 Mb             
                        try
                        {
                            this.toolStripProgressBar1.Value = Math.Min(this.toolStripProgressBar1.Maximum, e.ProgressPercentage);
                        }
                        catch { }
                        this.statusStrip1.Refresh();
                    });                backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object o, RunWorkerCompletedEventArgs x)
                    {
                        string SummaryText = String.Format("下载完成");
                        backgroundWorker.ReportProgress((int)(1), SummaryText);
                    });                backgroundWorker.RunWorkerAsync();
                }            
            }
    调用方法:
    string vFtpUrl = "yiduoi001.gicp.net";
    string vUserID = "ecff";
    string vPassWord = "ecSffn";
    string vPath = "ecDownload";            
    Download(vFtpUrl, vPath, vUserID, vPassWord, @"e:\test\qqbb");  
      

  9.   

    借贵地咨询另外一个问题,关于文件加密的问题,我想利用XML文件作媒介实现数据交换,但是XML文件用记事本很容打开,对文件的安全性不好,请问用生命方法可以对XML文件内容加密?