3

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

4

1 に答える 1

5

最終的に別のルートをたどったとしても、私は戻ってきて、 WebClientをサブクラス化し、すべての FTP 要求が「アクティブな」転送であることを確認する方法についての回答を提供することにしました。これには、新しい型を追加するために PowerShell v2 以降が必要です。PowerShell v1 でこれを行う必要がある場合は、クラス定義をアセンブリにコンパイルして読み込むことができます。

UseBinaryまた、FtpWebRequest クラスのプロパティは、プロパティと同じ方法で簡単に公開できます(UsePassive設定する必要がある場合)。

$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")
于 2013-03-15T16:14:23.747 に答える