Powershell: need to create an “active” ftp transfe

2019-05-23 21:23发布

问题:

I am using the following script file (ftp_test_2.ps1) to transfer files to an ftp server:

#we specify the directory where all files that we want to upload are contained 
$Dir="C:/Users/you-who/Documents/textfiles/"
#ftp server

$ftp = "ftp://192.168.100.101:21/"
$user = "aP_RDB"
$pass = "pw"
$webclient = New-Object System.Net.WebClient 
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)  

#list every txt file
foreach($item in (dir $Dir "*.txt"))
{ 
    "creating URI..."
    $uri = New-Object System.Uri($ftp+$item.Name) 
    $uri
    "attempting upload... $item"
    $webclient.UploadFile($uri, $item.FullName) 
 } 

This works fine when the $ftp is set to the local host and also connecting to another ftp test server. However, on the production ftp server, the server rejects the upload with the Powershell error:

Exception calling "UploadFile" with "2" argument(s): "The remote server returned an error: 227 Entering Passive Mode (192,168,101,99,228,67)."

At C:\Users\you-who\Documents\SandBox\ftp_test_2.ps1:17 char:24

\+$webclient.UploadFile <<<< ($uri, $item.FullName)
     \+CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
     \+ FullyQualifiedErrorId : DotNetMethodExceptionPP

On the production server there is a FileZilla server running. The messages in the server UI do not "seem" to show any errors:

(000029)2/5/2013 5:58:53 AM - (not logged in) (192.168.100.101)> USER aP_RDB
(000029)2/5/2013 5:58:53 AM - (not logged in) (192.168.100.101)> 331 Password required for ap_rdb
(000029)2/5/2013 5:58:53 AM - (not logged in) (192.168.100.101)> PASS *******
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> 230 Logged on
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> OPTS utf8 on
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> 200 UTF8 mode enabled
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> PWD
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> 257 "/" is current directory.
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> CWD /
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> 250 CWD successful. "/" is current directory.
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> TYPE I
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> 200 Type set to I
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> PASV
(000029)2/5/2013 5:58:53 AM - ap_rdb (192.168.100.101)> 227 Entering Passive Mode   (192,168,101,99,228,74)
(000029)2/5/2013 5:59:14 AM - ap_rdb (192.168.100.101)> disconnected.

From my FileZilla ftp client on my laptop, I can connect and put/get files on the production ftp server IF I set the "transfer mode" to "active" (in the FileZilla client) for the connection to the production ftp server.

Since I cannot change the production server, is there a way to set the transfer mode to "active" from within Powershell somewhere in my script above? I searched the web and MS sites for help on this, but could not find anything on . Any help greatly appreciated.

-Dave Ef

回答1:

Even though you ended up going a different route - I decided to come back and provide the answer on how to sub class WebClient and ensure that all FTP requests are "active" transfers. This requires PowerShell v2 and above to add a new type. If you need to do this in PowerShell v1, you can compile the class definition to an assembly and load it.

Also of note, you can easily expose the UseBinary property of the FtpWebRequest class in the same manner as the UsePassive property - if you need to set it as well.

$def = @"
public class ActiveFtpWebClient : System.Net.WebClient
{
  protected override System.Net.WebRequest GetWebRequest(System.Uri address)
  {
    System.Net.WebRequest request = base.GetWebRequest(address);
    if (request is System.Net.FtpWebRequest)
    {
      (request as System.Net.FtpWebRequest).UsePassive = false;
    }
    return request;
  }
}
"@

Add-Type -TypeDefinition $def
$ftp = New-Object ActiveFtpWebClient
$ftp.DownloadString("ftp://server/file.txt")