我在 WinSCP 网站上读到,您可以使用方法
Session.PutFile
在远程 FTP 服务器上创建文件,并使用 MemoryStream
在远程目录上创建对象。
显示的语法似乎缺少一些东西
https://winscp.net/eng/docs/library_session_putfile
它提到创建
MemoryStream
,然后传递远程目录路径和文件名的参数。
我在我创建的名为
SFTPCreatetrigger
的函数中使用它,因为名称表明重点是当每个文件上传到另一个文件时,使用它在单独的目录上创建具有相同名称的等效触发器文件。
但是我不断收到错误 New-Object:
无法将“System.Object[]”转换为参数“ComObject”所需的类型“System.String”。不支持指定的方法。
## ---------------------------------------------------------
## Function to Create file on Remote Directory
## ---------------------------------------------------------
Function SftpCreateTriggerFile
{
param
(
[string]$FtpServer,
[string]$FtpTriggerDirectory,
[string]$FtpUsername,
[string]$FtpPassword,
[string]$FtpSshHostKeyFingerprint
)
[hashtable]$Return = @{}
## Get initial time
$dt = Get-Date
$StartTime = Get-Date $dt -f "MMddyy HH:mm:ss"
$StartTimeUtc = $dt.ToUniversalTime().ToString("MMddyy HH:mm:ss")
## Load WinSCP .NET assembly
[Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\WinSCP\WinSCPnet.dll") | Out-Null
## Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
$sessionOptions.HostName = $FtpServer
$sessionOptions.UserName = $FtpUsername
$sessionOptions.Password = $FtpPassword
$sessionOptions.PortNumber = 22
$sessionOptions.SshHostKeyFingerprint = $FtpSshHostKeyFingerprint
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Upload files
$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.TransferMode = [WinSCP.TransferMode]::Automatic
$transferOptions.FilePermissions = $null
$transferOptions.PreserveTimestamp = $false
$transferOptions.ResumeSupport.State = [WinSCP.TransferResumeSupportState]::Off
$transferResult = $session.PutFile((New-Object System.IO.MemoryStream, ($FtpTriggerDirectory + $file.fullname)), $transferOptions)
# Throw on any error
$transferResult.Check()
if ($transferResult.Transfers.Count -gt 0)
{
$Return.IsSuccess = $true
$Return.StandardOutput = "Success"
}
else
{
$Return.IsSuccess = $false
$Return.StandardOutput = "Issue occurred creating trigger file on remote directory $FtpTriggerDirectory. No file created."
}
## Calculate time elapsed
$ExecTime = [math]::Round(([datetime]::Now - ([datetime]::ParseExact($StartTime,'MMddyy HH:mm:ss',$null))).TotalSeconds)
}
catch [Exception]
{
$Return.IsSuccess = $false
$Return.StandardOutput = $_.Exception.Message
## Calculate time elapsed
$ExecTime = [math]::Round(([datetime]::Now - ([datetime]::ParseExact($StartTime,'MMddyy HH:mm:ss',$null))).TotalSeconds)
}
finally
{
$Return.StartTime = $StartTime
$Return.StartTimeUtc = $StartTimeUtc
$Return.ExecTime = $ExecTime
## Disconnect and cleanup
$session.Dispose()
}
Return $Return
}
上面是函数,下面是我要执行的
## Set up wildcards to download files
$arrFiles = @(Get-ChildItem $LocalDirectory -Filter "*.txt")
foreach ($file in $arrFiles)
{
$arrReturnResults = SftpUploadWithWildcards -FtpServer $FtpServer -ftpdirectory $FtpDirectory -FtpUsername $FtpUsername -FtpPassword $FtpPassword -FtpSshHostKeyFingerprint $FtpSshHostKeyFingerprint -LocalDirectory $LocalDirectory -FileNameWildcards $file.Name
$ProcessName = "Upload($FtpServer):FromDir($LocalDirectory):Files("+$file.Name+")"
if ($arrReturnResults.IsSuccess)
{
$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Success"; Details = ""; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}
## File Archive
# Move-Item ($LocalDirectory+$file.Name) ($LocalDirectory+"Archive") -Force -ErrorAction Stop
## Create 0 byte file with the same name to the trigger folder on remote server
$arrReturnResults = SftpCreateTriggerFile -FtpServer $FtpServer -ftpTriggerdirectory $FtpTriggerDirectory -FtpUsername $FtpUsername -FtpPassword $FtpPassword -FtpSshHostKeyFingerprint $FtpSshHostKeyFingerprint
$ProcessName = "Upload($FtpServer):FromDir($LocalDirectory):TriggerFiles("+$file.Name+")"
if ($arrReturnResults.IsSuccess)
{
$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Success"; Details = ""; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}
}
else
{
$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Failed"; Details = $arrReturnResults.StandardOutput; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}
}
}
else
{
$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Failed"; Details = $arrReturnResults.StandardOutput; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}
}
}
我的所有变量(
$ftpserver
、$ftpusername
、$ftptriggerdirectory
等)都设置为正确的值。似乎只是在呼唤
New-Object System.IO.MemoryStream
单独创建一个新的 MemoryStream
对象
CanRead : True
CanSeek : True
CanWrite : True
Capacity : 0
Length : 0
Position : 0
CanTimeout : False
ReadTimeout :
WriteTimeout :
但是我无法为其分配我想要的名称(这实际上是最后一个经历 foreach 循环的
$file
)
我已经阅读了
MemoryStream
使用并发现您需要引用 byte
数组?然而,我只是希望它在远程目录上创建一个对象,如我在 Martin Prikryl 本人找到的示例中所述。
如果您的目标是创建一个 empty 文件(从新的空
MemoryStream
),那么问题是使用三个参数调用 Session.PutFile
的语法不正确。应该是:
$session.PutFile(
(New-Object System.IO.MemoryStream), # stream
($FtpTriggerDirectory + $file.fullname), # remoteFilePath
$transferOptions) # options
(
$FtpTriggerDirectory + $file.fullname
两边的括号是多余的)
另请注意,
Session.PutFile
不会返回任何内容。因此,所有分配 $transferResult
并使用它的代码都会失败。