如何使用winscpnet.dll并发上传文件。我想设置winscp.exe实例,它们可以使用脚本或c#同时运行到x个winscp.exe实例。
其他线程已经在下面的链接中提到了文档,但该代码将查看远程服务器并使用session.GetFiles同时下载x session中的所有文件 https://winscp.net/eng/docs/library_example_parallel_transfers#powershell
我希望做类似但希望使用session.PutFiles从目录上传文件。
winscpnet.dll代码中内置了一个函数,它将枚举远程目录,但没有任何东西可以用于相反的操作。循环遍历本地目录并启动winscp.exe的五个实例,完成后直到所有文件都完成,session.Putfiles传输。
这一点很重要的原因是,将它们一次上传到远程sftp服务器所需要的时间要长得多。
答案 0 :(得分:1)
WinSCP .NET程序集中没有用于枚举本地文件的API,因为它与远程连接无关。
在PowerShell中实际上是一个API,Get-ChildItem
。
除此之外,代码与下载代码几乎相同(除了明显的差异,例如使用Session.PutFiles
而不是Session.GetFiles
)。
您引用的文章现在包含upload in parallel connections over SFTP protocol in C#的完整代码。
答案 1 :(得分:1)
如果你仍然需要它,我们就去吧。
#Powershell script to upload files from a local dire
param (
$sessionUrl = "sftp://tester:password;fingerprint=ssh-rsa 2048 ba:5d:a4:1b:0a:73:30:cf:90:dd:e3:ef:6c:9e:1d:94@localhost",
$remotePath = "/",
$localPath = "C:\Users\your\test\upload",
$batches = 3
)
#Upload data to local Rebex Tiny SFTP
try
{
# Load WinSCP .NET assembly
$dllPath = (Join-Path $PSScriptRoot "WinSCPnet.dll")
# Load WinSCP .NET assembly
Add-Type -Path $dllPath
$started = Get-Date
# Build list of local files and sort them from larges to smallest
$files = Get-ChildItem $localPath | Sort-Object Length -Descending
# Calculate total size of all files
$total = ($files | Measure-Object -Property Length -Sum).Sum
# And batch size
$batch = [int]($total / $batches)
Write-Host ("Will upload {0} files totaling {1} bytes in {2} parallel batches, {3} bytes on average in each" -f $files.Count, $total, $batches, $batch)
$start = 0
$sum = 0
$no = 0
for ($i = 0; $i -lt $files.Count; $i++)
{
$sum += $files[$i].Length
# Found enough files for the next batch
if (($sum -ge $batch) -or ($i -eq $files.Count - 1))
{
Write-Host ("Starting batch {0} to upload {1} files totaling {2}" -f $no, ($i - $start + 1), $sum)
$fileList = $files[$start..$i] -join ";"
# Start the background job for the batch
Start-Job -Name "Batch $no" -ArgumentList $dllPath, $sessionUrl, $localPath, $remotePath, $no, $fileList {
param (
[Parameter(Position = 0)]
$dllPath,
[Parameter(Position = 1)]
$sessionUrl,
[Parameter(Position = 2)]
$localPath,
[Parameter(Position = 3)]
$remotePath,
[Parameter(Position = 4)]
$no,
[Parameter(Position = 5)]
$fileList
)
try
{
Write-Host ("Starting batch {0}" -f $no)
# Load WinSCP .NET assembly.
# Need to use an absolute path as the Job is started from user's documents folder.
Add-Type -Path $dllPath
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($sessionUrl)
try
{
Write-Host ("Connecting batch {0}..." -f $no)
$session = New-Object WinSCP.Session
$session.Open($sessionOptions)
$files = $fileList -split ";"
# Upload the files selected for this batch
foreach ($file in $files)
{
$localFilePath = "$localPath\$file"
$remoteFilePath = "$remotePath/$file"
Write-Host "Uploading $localFilePath to $remoteFilePath in $no"
$session.PutFiles($session.EscapeFileMask($localFilePath), $remoteFilePath).Check()
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
Write-Host ("Batch {0} done" -f $no)
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}
} | Out-Null
# Reset for the next batch
$no++
$sum = 0
$start = $i + 1
}
}
Write-Host "Waiting for batches to complete"
Get-Job | Receive-Job -Wait
Write-Host "Done"
$ended = Get-Date
Write-Host ("Took {0}" -f (New-TimeSpan -Start $started -End $ended))
exit 0
}
catch [Exception]
{
Write-Host $_.Exception.Message
exit 1
}