PowerShell FTPS 上传失败,并显示"System error."



问题:

客户要求我们将提取的数据从我们的系统上传到他们的 box.com 平台,而不是我们正常的SFTP实用程序。我有 box.com 凭据,并且知道它们需要FTPS而不是SFTP,并且需要被动模式。我从ThomasMaurer的Powershell FTP上传和下载脚本中摘录了一个片段。我的服务器上的Powershell版本是4.0

代码片段为:

#config 
$Username = "username@host.com"
$Password = "redactedpassword"
$LocalFile = "C:pathtomyfile.csv"
$RemoteFile = "ftp://ftp.box.com:990/file.csv"
#Create FTPWebRequest
$FTPRequest = [System.Net.FtpWebRequest]::Create($RemoteFile)
$FTPRequest = [System.Net.FtpWebRequest]$FTPRequest
$FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
$FTPRequest.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)
$FTPRequest.UseBinary = $true
$FTPRequest.UsePassive = $true
#read file for upload
$FileContent = gc -en byte $LocalFile
$FTPRequest.ContentLength = $FileContent.Length
#get stream request by bytes
$run = $FTPRequest.GetRequestStream()
$run.Write($FileContent,0,$FileContent.Length)
#cleanup
$run.Close()
$run.Dispose()

错误:

Exception calling "GetRequestStream" with "0" argument(s): "System error." At C:pathtomypowershellscript.ps1:28 char:1
+ $Run = $FTPRequest.GetRequestStream()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: () [], MethodInvocationException
+ FullyQualifiedErrorId: WebException

我还在调用 $FileContent.Length 属性和$run.close$run.dispose()时收到下游错误。

是否有人仅使用 PowerShell 4.0 命令成功地自动装箱(特别是)或被动隐式 ssl,您是否有我可以重用的可靠模式? 非常感谢

我正在使用派生版本的System.Net.WebClient上传文件,该版本支持TLS上的FTP。这可以通过在PowerShell中嵌入C#代码轻松实现:

$typeDefinition = @"
using System;
using System.Net;
public class FtpClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri address)
    {
        FtpWebRequest ftpWebRequest = base.GetWebRequest(address) as FtpWebRequest;
        ftpWebRequest.EnableSsl = true;
        return ftpWebRequest;
    }
}
"@
Add-Type -TypeDefinition $typeDefinition
$ftpClient = New-Object FtpClient
$ftpClient.UploadFile("ftp://your-ftp-server/yourfile.name", "STOR", "C:YourLocalFile.name")

@h0r41i0的答案通过使用WebClient解决了问题。但是由于WebClient内部使用(Ftp)WebRequest,它本身不能成为解决方案。

我假设发生"系统错误"是因为 OP 尝试连接到具有不安全连接的安全端口 (990)。

或者因为文件太大,OP 代码试图将其整个读取到内存中:

$FileContent = gc -en byte $LocalFile

无论哪种情况,都没有理由放弃FtpWebRequest。只需使用安全连接(FtpWebRequest.EnableSsl)。以及将数据从文件馈送到FTP流的有效方法,例如Stream.CopyTo

$request = [Net.WebRequest]::Create("ftp://ftp.example.com/remote/path/file.zip")
$request.Credentials = New-Object System.Net.NetworkCredential("username", "password")
$request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile 
$request.EnableSsl = $True
$fileStream = [System.IO.File]::OpenRead("C:localpathfile.zip")
$ftpStream = $request.GetRequestStream()
$fileStream.CopyTo($ftpStream)
$ftpStream.Dispose()
$fileStream.Dispose()

有关其他选项,请参阅使用 PowerShell 使用 FTP 上传文件。

但请注意,.NET 框架不支持隐式 TLS(这是 990 的典型用法)。只有显式 TLS。但是对显式TLS的支持更为常见。请参阅 .NET FtpWebRequest 是否同时支持隐式 (FTPS) 和显式 (FTPES)?

可能为时已晚,无法对原始提问者有用,但我发现另一个答案对我有用:西里尔·古普塔对使用 powershell 使用 ftp 上传文件的回答

这是我的修订版,包括URL编码(因为 box.com 用户名是包含"at符号"的电子邮件地址):

## https://stackoverflow.com/a/2485696/537243
## User comment complains can't turn off passive mode, 
## but that is exactly what we want here!
[Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null
# config 
$Username = "foo@bar.com"
$Password = "s3cr3tpAssw0rd"
$Servername = "ftp.box.com"
# This is what we need URI it to look like:
#   ftp://foo%40bar.com:s3cr3tpAssw0rd@ftp.box.com/
$baseURI = "ftp://$([System.Web.HttpUtility]::UrlEncode($Username)):$([System.Web.HttpUtility]::UrlEncode($Password))@$($Servername)"
$LocalFile = "C:tmpto_uploaddata.csv"
$RemoteFile = "date.csv"
$ftpURI = "$($baseURI)/$($RemoteFile)"
Write-output "ftp uri: $($ftpURI)";
$webclient = New-Object -TypeName System.Net.WebClient;
$ftpURI = New-Object -TypeName System.Uri -ArgumentList $ftpURI; #"convert" it
$webclient.UploadFile($ftpURI, $LocalFile);
Write-output  "Uploaded $($LocalFile) ... "; # of course since we didn't use try/catch or other error dectection this is a bit presuming.

还应该注意,此示例使用普通 FTP,而不是 FTPS 或 SFTP。

最新更新