如何解决 C# 应用程序中的 FTP 超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/787116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:07:53  来源:igfitidea点击:

How to solve FTP timeouts in C# app

c#ftp

提问by

I'm using the following C# code to FTP a ~40MB CSV file from a remote service provider. Around 50% of the time, the download hangs and eventually times out. In my app log, I get a line like:

我正在使用以下 C# 代码从远程服务提供商通过 FTP 传输一个 ~40MB 的 CSV 文件。大约 50% 的时间,下载挂起并最终超时。在我的应用程序日志中,我得到如下一行:

> Unable to read data from the transport
> connection: A connection attempt
> failed because the connected party did
> not properly respond after a period of
> time, or established connection failed
> because connected host has failed to
> respond.

When I download the file interactively using a graphical client like LeechFTP, the downloads almost never hang, and complete in about 45 seconds. I'm having a hell of a time understanding what's going wrong.

当我使用像 LeechFTP 这样的图形客户端以交互方式下载文件时,下载几乎从不挂起,并在大约 45 秒内完成。我花了很长时间才明白出了什么问题。

Can anyone suggest how I can instrument this code to get more insight into what's going on, or a better way to download this file? Should I increase the buffer size? By how much? Avoid the buffered writes to disk and try to swallow the whole file in memory? Any advice appreciated!

任何人都可以建议我如何检测此代码以更深入地了解正在发生的事情,或者下载此文件的更好方?我应该增加缓冲区大小吗?到多少?避免缓冲写入磁盘并尝试在内存中吞下整个文件?任何建议表示赞赏!

...

private void CreateDownloadFile()
    {
        _OutputFile = new FileStream(_SourceFile, FileMode.Create);
    }
public string FTPDownloadFile()
    {
        this.CreateDownloadFile();

        myReq = (FtpWebRequest)FtpWebRequest.Create(new Uri(this.DownloadURI));
        myReq.Method = WebRequestMethods.Ftp.DownloadFile;
        myReq.UseBinary = true;
        myReq.Credentials = new NetworkCredential(_ID, _Password);

        FtpWebResponse myResp = (FtpWebResponse)myReq.GetResponse();
        Stream ftpStream = myResp.GetResponseStream();

        int bufferSize = 2048;
        int readCount;
        byte[] buffer = new byte[bufferSize];
        int bytesRead = 0;
        readCount = ftpStream.Read(buffer, 0, bufferSize);

        while (readCount > 0)
        {
            _OutputFile.Write( buffer, 0, readCount );
            readCount = ftpStream.Read( buffer, 0, bufferSize );

            Console.Write( '.' );    // show progress on the console
            bytesRead += readCount;
        }
        Console.WriteLine();
        logger.logActivity( "    FTP received " + String.Format( "{0:0,0}", bytesRead ) + " bytes" );

        ftpStream.Close();
        _OutputFile.Close();
        myResp.Close();
        return this.GetFTPStatus();
    }

    public string GetFTPStatus()
    {
        return ((FtpWebResponse)myReq.GetResponse()).StatusDescription;
    }

回答by gillonba

I haven't dealt with FTP on a code level, but FTP supports resuming. Maybe you could have it automatically try to resume the upload when it times out

我没有在代码级别处理过 FTP,但 FTP 支持恢复。也许你可以让它在超时时自动尝试恢复上传

回答by Jonathan Allen

I suggest you don't use FtpWebRequest for FTP access. FtpWebRequest is the most brain-dead FTP API I have every seen.

我建议您不要使用 FtpWebRequest 进行 FTP 访问。FtpWebRequest 是我见过的最脑残的 FTP API。

Currently I use FtpClient http://www.codeplex.com/ftpclient

目前我使用 FtpClient http://www.codeplex.com/ftpclient

I also have had good luck with IndySockets http://www.indyproject.org/index.en.aspx

我也很幸运使用 IndySockets http://www.indyproject.org/index.en.aspx

回答by Tom

I tried to use FTPClient as suggested above and got the same timeout error, FTPClient uses FtpWebRequest so I must be missing something but I don't see the point.

我尝试按照上面的建议使用 FTPClient 并得到相同的超时错误,FTPClient 使用 FtpWebRequest 所以我一定遗漏了一些东西,但我没有看到这一点。

After some more research I found that -1 is the value for infinity

经过更多研究,我发现 -1 是无穷大的值

For my purpose it is okay to use infinity so I went with that, problem solved.

出于我的目的,可以使用无穷大,所以我就这样做了,问题解决了。

Here is my code:

这是我的代码:

//gets file from FTP site.

//从FTP站点获取文件。

        FtpWebRequest reqFTP;

        string fileName = @"c:\downloadDir\localFileName.txt";
        FileInfo downloadFile = new FileInfo(fileName);
        string uri = "ftp://ftp.myftpsite.com/ftpDir/remoteFileName.txt";


        FileStream outputStream = new FileStream(fileName, FileMode.Append);

        reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
        reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
        reqFTP.UseBinary = true;
        reqFTP.KeepAlive = false;
        reqFTP.Timeout = -1;
        reqFTP.UsePassive = true;
        reqFTP.Credentials = new NetworkCredential("userName", "passWord");
        FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
        Stream ftpStream = response.GetResponseStream();
        long cl = response.ContentLength;
        int bufferSize = 2048;
        int readCount;
        byte[] buffer = new byte[bufferSize];
        readCount = ftpStream.Read(buffer, 0, bufferSize);
        Console.WriteLine("Connected: Downloading File");
        while (readCount > 0)
        {
            outputStream.Write(buffer, 0, readCount);
            readCount = ftpStream.Read(buffer, 0, bufferSize);
            Console.WriteLine(readCount.ToString());
        }

        ftpStream.Close();
        outputStream.Close();
        response.Close();
        Console.WriteLine("Downloading Complete");