FTP C# 中的多个文件无需重新建立连接
FTP multiple files in C# without reestablishing connection
FTP 协议旨在支持控制通道,并使用该控制通道告诉服务器打开 TCP 连接和传输文件。
发送或接收文件的服务器不必与 FTP 控制通道连接的服务器相同。它可以是 "triangle" 类型的连接。
还允许客户端在控制通道上登录一次,并重复告诉服务器传输文件,而无需重新登录控制通道。
显然,当 MS 创建 C# FtpWebRequest
class.
时,这个概念已经完全脱离了 MS
我需要做的正是 FTP 协议的设计目的:
连接到服务器
传入凭据
创建目录(并愉快地忽略 'already exists' 错误)
重复传输文件到服务器
退出控制通道
我肯定没有在 FtpWebRequest
class 中看到这种能力。或者在 C# 代码中似乎允许这种流程的任何东西。
我看过:
和 Upload Multiple files to FTP in c#
等
但是 none 这似乎允许按预期的方式进行控制。
我可以指定 KeepAlive
属性,但循环必须重复调用 WebRequest.Create(targetName);
函数,这将创建一个新连接,并获得一个新响应。然后它们就会超出范围或成为孤儿,因此根据定义,它们将被销毁。因此连接必须关闭,然后必须重新打开。对于数据连接来说,这没问题,但是操作 CONTROL 端口的能力在哪里?
class 不允许用户区分 CONTROL 端口和 DATA 端口,正如 FTP 规范定义的那样。
有没有办法使用 C# class 来实现 FTP 它本来的样子?因为在微软的狭隘思维中,整个世界看起来就像一个 HTTPGet/Response 协议。
如有任何建议,我们将不胜感激。
-斯科蒂
edtFTPnet looks promising, as did FluentFTP
然而,最终,为此类项目使用 DLL 程序集或库,无论是 LGPL 还是 MIT 或其他任何项目,都可能导致恶意攻击的人将 DLL 替换为原来的 DLL注入某种形式的恶意软件。因为来源是免费的。
最后,最好自己写一个,把代码直接嵌入到可执行文件中。额外的努力是值得的。
所以我将其标记为已回答。对评论表示赞赏。
在 .NET Framework 中 FtpWebRequest
在连接池之上工作。所以 它实际上隐式地重用 底层 FTP 连接,只要 FtpWebRequest.KeepAlive
设置为其默认值 true
.
当 KeepAlive
设置为 true
时,底层 FTP(控制)连接 未关闭 ,当请求完成时.当您使用相同的主机、端口和用户名创建 FtpWebRequest
的另一个实例时,来自先前请求的连接将被重用。
以两个文件上传请求到同一 FTP 服务器的简单示例为例:
WebRequest request1 = WebRequest.Create("ftp://ftp.example.com/file1.zip");
request1.Credentials = new NetworkCredential("username", "password");
request1.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(@"C:\path\file1.zip"))
using (Stream ftpStream = request1.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
WebRequest request2 = WebRequest.Create("ftp://ftp.example.com/file2.zip");
request2.Credentials = new NetworkCredential("username", "password");
request2.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(@"C:\path\file2.zip"))
using (Stream ftpStream = request2.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
如果您 enable .NET network logging,您将看到只有一个 FTP 控制连接打开到服务器:
FtpWebRequest#45004109::.ctor(ftp://ftp.example.com/file1.zip)
FtpWebRequest#45004109::GetRequestStream(Method=STOR.)
Current OS installation type is 'Client'.
RAS supported: True
FtpControlStream#21454193 - Created connection from 127.0.0.1:60360 to 93.184.216.34:2121.
Associating FtpWebRequest#45004109 with FtpControlStream#21454193
FtpControlStream#21454193 - Received response [220 ...]
FtpControlStream#21454193 - Sending command [USER username]
FtpControlStream#21454193 - Received response [331 Password required for username]
FtpControlStream#21454193 - Sending command [PASS ********]
FtpControlStream#21454193 - Received response [230 Logged on]
FtpControlStream#21454193 - Sending command [OPTS utf8 on]
FtpControlStream#21454193 - Received response [202 UTF8 mode is always enabled. No need to send this command.]
FtpControlStream#21454193 - Sending command [PWD]
FtpControlStream#21454193 - Received response [257 "/" is current directory.]
FtpControlStream#21454193 - Sending command [TYPE I]
FtpControlStream#21454193 - Received response [200 Type set to I]
FtpControlStream#21454193 - Sending command [PASV]
FtpControlStream#21454193 - Received response [227 Entering Passive Mode (93,184,216,34,247,106)]
FtpControlStream#21454193 - Sending command [STOR file1.zip]
FtpControlStream#21454193 - Received response [150 Opening data channel for file upload to server of "/file1.zip"]
FtpControlStream#21454193 - Received response [226 Successfully transferred "/file1.zip"]
FtpWebRequest#45004109::(Releasing FTP connection#21454193.)
FtpWebRequest#58870012::.ctor(ftp://ftp.example.com/file2.zip)
FtpWebRequest#58870012::GetRequestStream(Method=STOR.)
Associating FtpWebRequest#58870012 with FtpControlStream#21454193
FtpControlStream#21454193 - Sending command [PASV]
FtpControlStream#21454193 - Received response [227 Entering Passive Mode (93,184,216,34,247,142)]
FtpControlStream#21454193 - Sending command [STOR file2.zip]
FtpControlStream#21454193 - Received response [150 Opening data channel for file upload to server of "/file2.zip"]
FtpControlStream#21454193 - Received response [226 Successfully transferred "/file2.zip"]
FtpWebRequest#58870012::(Releasing FTP connection#21454193.)
请注意,这在 .NET Core 中不起作用:
FTP 协议旨在支持控制通道,并使用该控制通道告诉服务器打开 TCP 连接和传输文件。
发送或接收文件的服务器不必与 FTP 控制通道连接的服务器相同。它可以是 "triangle" 类型的连接。
还允许客户端在控制通道上登录一次,并重复告诉服务器传输文件,而无需重新登录控制通道。
显然,当 MS 创建 C# FtpWebRequest
class.
我需要做的正是 FTP 协议的设计目的:
连接到服务器
传入凭据
创建目录(并愉快地忽略 'already exists' 错误)
重复传输文件到服务器
退出控制通道
我肯定没有在 FtpWebRequest
class 中看到这种能力。或者在 C# 代码中似乎允许这种流程的任何东西。
我看过:
和 Upload Multiple files to FTP in c#
等
但是 none 这似乎允许按预期的方式进行控制。
我可以指定 KeepAlive
属性,但循环必须重复调用 WebRequest.Create(targetName);
函数,这将创建一个新连接,并获得一个新响应。然后它们就会超出范围或成为孤儿,因此根据定义,它们将被销毁。因此连接必须关闭,然后必须重新打开。对于数据连接来说,这没问题,但是操作 CONTROL 端口的能力在哪里?
class 不允许用户区分 CONTROL 端口和 DATA 端口,正如 FTP 规范定义的那样。
有没有办法使用 C# class 来实现 FTP 它本来的样子?因为在微软的狭隘思维中,整个世界看起来就像一个 HTTPGet/Response 协议。
如有任何建议,我们将不胜感激。
-斯科蒂
edtFTPnet looks promising, as did FluentFTP
然而,最终,为此类项目使用 DLL 程序集或库,无论是 LGPL 还是 MIT 或其他任何项目,都可能导致恶意攻击的人将 DLL 替换为原来的 DLL注入某种形式的恶意软件。因为来源是免费的。
最后,最好自己写一个,把代码直接嵌入到可执行文件中。额外的努力是值得的。
所以我将其标记为已回答。对评论表示赞赏。
在 .NET Framework 中 FtpWebRequest
在连接池之上工作。所以 它实际上隐式地重用 底层 FTP 连接,只要 FtpWebRequest.KeepAlive
设置为其默认值 true
.
当 KeepAlive
设置为 true
时,底层 FTP(控制)连接 未关闭 ,当请求完成时.当您使用相同的主机、端口和用户名创建 FtpWebRequest
的另一个实例时,来自先前请求的连接将被重用。
以两个文件上传请求到同一 FTP 服务器的简单示例为例:
WebRequest request1 = WebRequest.Create("ftp://ftp.example.com/file1.zip");
request1.Credentials = new NetworkCredential("username", "password");
request1.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(@"C:\path\file1.zip"))
using (Stream ftpStream = request1.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
WebRequest request2 = WebRequest.Create("ftp://ftp.example.com/file2.zip");
request2.Credentials = new NetworkCredential("username", "password");
request2.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(@"C:\path\file2.zip"))
using (Stream ftpStream = request2.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
如果您 enable .NET network logging,您将看到只有一个 FTP 控制连接打开到服务器:
FtpWebRequest#45004109::.ctor(ftp://ftp.example.com/file1.zip)
FtpWebRequest#45004109::GetRequestStream(Method=STOR.)
Current OS installation type is 'Client'.
RAS supported: True
FtpControlStream#21454193 - Created connection from 127.0.0.1:60360 to 93.184.216.34:2121.
Associating FtpWebRequest#45004109 with FtpControlStream#21454193
FtpControlStream#21454193 - Received response [220 ...]
FtpControlStream#21454193 - Sending command [USER username]
FtpControlStream#21454193 - Received response [331 Password required for username]
FtpControlStream#21454193 - Sending command [PASS ********]
FtpControlStream#21454193 - Received response [230 Logged on]
FtpControlStream#21454193 - Sending command [OPTS utf8 on]
FtpControlStream#21454193 - Received response [202 UTF8 mode is always enabled. No need to send this command.]
FtpControlStream#21454193 - Sending command [PWD]
FtpControlStream#21454193 - Received response [257 "/" is current directory.]
FtpControlStream#21454193 - Sending command [TYPE I]
FtpControlStream#21454193 - Received response [200 Type set to I]
FtpControlStream#21454193 - Sending command [PASV]
FtpControlStream#21454193 - Received response [227 Entering Passive Mode (93,184,216,34,247,106)]
FtpControlStream#21454193 - Sending command [STOR file1.zip]
FtpControlStream#21454193 - Received response [150 Opening data channel for file upload to server of "/file1.zip"]
FtpControlStream#21454193 - Received response [226 Successfully transferred "/file1.zip"]
FtpWebRequest#45004109::(Releasing FTP connection#21454193.)
FtpWebRequest#58870012::.ctor(ftp://ftp.example.com/file2.zip)
FtpWebRequest#58870012::GetRequestStream(Method=STOR.)
Associating FtpWebRequest#58870012 with FtpControlStream#21454193
FtpControlStream#21454193 - Sending command [PASV]
FtpControlStream#21454193 - Received response [227 Entering Passive Mode (93,184,216,34,247,142)]
FtpControlStream#21454193 - Sending command [STOR file2.zip]
FtpControlStream#21454193 - Received response [150 Opening data channel for file upload to server of "/file2.zip"]
FtpControlStream#21454193 - Received response [226 Successfully transferred "/file2.zip"]
FtpWebRequest#58870012::(Releasing FTP connection#21454193.)
请注意,这在 .NET Core 中不起作用: