使用FtpWebRequest上传大文件到FTP会导致“底层连接已关闭”

本文关键字:连接 FtpWebRequest 文件 FTP 使用 | 更新日期: 2023-09-27 18:15:18

我试图上传一个相对较大的文件到FTP服务器(250-300mb)。我在控制台应用程序中这样做。

当文件有几个MB时,我的程序可以正常工作,但是大的文件会导致:

System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive.

我尝试设置超时时间,但仍然得到错误。

任何想法如何修改我的代码,所以我没有得到错误?

我的上传代码:

using(var fs = File.OpenRead(zipFileName)) 
            {
                var ms = new MemoryStream();
                ms.SetLength(fs.Length);
                fs.Read(ms.GetBuffer(), 0, (int) fs.Length);
                FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpUrl + "/" + zipFileName);
                ftp.Credentials = new NetworkCredential(ftpUid, ftpPassword);
                ftp.Timeout = 30000;
                ftp.KeepAlive = true;
                ftp.UseBinary = true;
                ftp.Method = WebRequestMethods.Ftp.UploadFile;

                byte[] buffer = new byte[ms.Length];
                ms.Read(buffer, 0, buffer.Length);
                ms.Close();
                Stream ftpstream = ftp.GetRequestStream();
                ftpstream.Write(buffer, 0, buffer.Length);
                ftpstream.Close();
            }

使用FtpWebRequest上传大文件到FTP会导致“底层连接已关闭”

我用你的代码上传了一个1gb的文件到我的FTP服务器。我也得到system.net.webeexception。为了解决这个问题,我将超时设置为-1(不超时)。在那之后,上传成功了。

ftp.Timeout = -1; // No Timeout

另一个注意事项,我不知道为什么你读文件到MemoryStream,然后把它放入一个字节[]缓冲区。将FileStream复制到FTP RequestStream会更快,使用更少的内存。

using (var fs = File.OpenRead(zipFileName))
{
    FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpUrl + "/" + zipFileName);
    ftp.Credentials = new NetworkCredential(ftpUid, ftpPassword);
    ftp.Timeout = -1;
    ftp.KeepAlive = true;
    ftp.UseBinary = true;
    ftp.Method = WebRequestMethods.Ftp.UploadFile;
    Stream ftpstream = ftp.GetRequestStream();
    fs.CopyTo(ftpstream); // Copy the FileStream to the FTP RequestStream
    ftpstream.Close();
    // You should also check the response
    FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
    Console.WriteLine("Code: {0}", response.StatusCode);
    Console.WriteLine("Desc: {0}", response.StatusDescription);
}