Ich möchte PowerShell verwenden, um Dateien mit FTP auf einen anonymen FTP-Server zu übertragen. Ich würde keine zusätzlichen Pakete verwenden. Wie?
Es darf kein Risiko bestehen, dass das Skript hängt oder abstürzt.
powershell
ftp
Magol
quelle
quelle
Antworten:
Ich bin nicht sicher, ob Sie das Skript zu 100% kugelsicher machen können, damit es nicht hängt oder abstürzt, da es Dinge gibt, die außerhalb Ihrer Kontrolle liegen (was ist, wenn der Server während des Uploads die Stromversorgung verliert?) - aber dies sollte eine solide Grundlage für den Einstieg bieten:
# create the FtpWebRequest and configure it $ftp = [System.Net.FtpWebRequest]::Create("ftp://localhost/me.png") $ftp = [System.Net.FtpWebRequest]$ftp $ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile $ftp.Credentials = new-object System.Net.NetworkCredential("anonymous","anonymous@localhost") $ftp.UseBinary = $true $ftp.UsePassive = $true # read in the file to upload as a byte array $content = [System.IO.File]::ReadAllBytes("C:\me.png") $ftp.ContentLength = $content.Length # get the request stream, and write the bytes into it $rs = $ftp.GetRequestStream() $rs.Write($content, 0, $content.Length) # be sure to clean up after ourselves $rs.Close() $rs.Dispose()
quelle
Es gibt auch andere Möglichkeiten. Ich habe das folgende Skript verwendet:
$File = "D:\Dev\somefilename.zip"; $ftp = "ftp://username:[email protected]/pub/incoming/somefilename.zip"; Write-Host -Object "ftp url: $ftp"; $webclient = New-Object -TypeName System.Net.WebClient; $uri = New-Object -TypeName System.Uri -ArgumentList $ftp; Write-Host -Object "Uploading $File..."; $webclient.UploadFile($uri, $File);
Mit dem folgenden Befehl können Sie ein Skript für das Windows-FTP-Befehlszeilenprogramm ausführen
ftp -s:script.txt
(Lesen Sie diesen Artikel )
Die folgende Frage zu SO beantwortet auch diese Frage: Wie schreibe ich FTP-Uploads und -Downloads?
quelle
$uri
ein Fehler ausgegeben. Ich ziehe es vor, die Anmeldeinformationen auf dem Client$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
Ich werde nicht behaupten, dass dies eleganter ist als die Lösung mit den höchsten Stimmen ... aber das ist auf seine eigene Weise cool (zumindest in meinen Augen LOL):
$server = "ftp.lolcats.com" $filelist = "file1.txt file2.txt" "open $server user $user $password binary cd $dir " + ($filelist.split(' ') | %{ "put ""$_""`n" }) | ftp -i -in
Wie Sie sehen können, wird dieser dinky integrierte Windows-FTP-Client verwendet. Viel kürzer und unkomplizierter. Ja, ich habe das tatsächlich benutzt und es funktioniert!
quelle
Einfachster Weg
Die einfachste Möglichkeit, eine Binärdatei mit PowerShell auf einen FTP-Server hochzuladen, ist die Verwendung von
WebClient.UploadFile
:$client = New-Object System.Net.WebClient $client.Credentials = New-Object System.Net.NetworkCredential("username", "password") $client.UploadFile("ftp://ftp.example.com/remote/path/file.zip", "C:\local\path\file.zip")
Erweiterte Optionen
Wenn Sie eine bessere Kontrolle benötigen, die
WebClient
diese nicht bietet (wie TLS / SSL-Verschlüsselung usw.), verwenden SieFtpWebRequest
. Einfache Möglichkeit ist, einfach eine KopieFileStream
zu FTP - Stream unter Verwendung vonStream.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 $fileStream = [System.IO.File]::OpenRead("C:\local\path\file.zip") $ftpStream = $request.GetRequestStream() $fileStream.CopyTo($ftpStream) $ftpStream.Dispose() $fileStream.Dispose()
Fortschrittsüberwachung
Wenn Sie den Upload-Fortschritt überwachen müssen, müssen Sie den Inhalt selbst in Blöcke kopieren:
$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 $fileStream = [System.IO.File]::OpenRead("C:\local\path\file.zip") $ftpStream = $request.GetRequestStream() $buffer = New-Object Byte[] 10240 while (($read = $fileStream.Read($buffer, 0, $buffer.Length)) -gt 0) { $ftpStream.Write($buffer, 0, $read) $pct = ($fileStream.Position / $fileStream.Length) Write-Progress ` -Activity "Uploading" -Status ("{0:P0} complete:" -f $pct) ` -PercentComplete ($pct * 100) } $fileStream.CopyTo($ftpStream) $ftpStream.Dispose() $fileStream.Dispose()
Ordner hochladen
Wenn Sie alle Dateien aus einem Ordner hochladen möchten, lesen Sie
PowerShell Script, um einen gesamten Ordner auf FTP hochzuladen
quelle
Ich habe kürzlich für Powershell verschiedene Funktionen für die Kommunikation mit FTP geschrieben, siehe https://github.com/AstralisSomnium/PowerShell-No-Library-Just-Functions/blob/master/FTPModule.ps1 . Mit der zweiten Funktion unten können Sie einen ganzen lokalen Ordner an FTP senden. Im Modul befinden sich sogar Funktionen zum rekursiven Entfernen / Hinzufügen / Lesen von Ordnern und Dateien.
#Add-FtpFile -ftpFilePath "ftp://myHost.com/folder/somewhere/uploaded.txt" -localFile "C:\temp\file.txt" -userName "User" -password "pw" function Add-FtpFile($ftpFilePath, $localFile, $username, $password) { $ftprequest = New-FtpRequest -sourceUri $ftpFilePath -method ([System.Net.WebRequestMethods+Ftp]::UploadFile) -username $username -password $password Write-Host "$($ftpRequest.Method) for '$($ftpRequest.RequestUri)' complete'" $content = $content = [System.IO.File]::ReadAllBytes($localFile) $ftprequest.ContentLength = $content.Length $requestStream = $ftprequest.GetRequestStream() $requestStream.Write($content, 0, $content.Length) $requestStream.Close() $requestStream.Dispose() } #Add-FtpFolderWithFiles -sourceFolder "C:\temp\" -destinationFolder "ftp://myHost.com/folder/somewhere/" -userName "User" -password "pw" function Add-FtpFolderWithFiles($sourceFolder, $destinationFolder, $userName, $password) { Add-FtpDirectory $destinationFolder $userName $password $files = Get-ChildItem $sourceFolder -File foreach($file in $files) { $uploadUrl ="$destinationFolder/$($file.Name)" Add-FtpFile -ftpFilePath $uploadUrl -localFile $file.FullName -username $userName -password $password } } #Add-FtpFolderWithFilesRecursive -sourceFolder "C:\temp\" -destinationFolder "ftp://myHost.com/folder/" -userName "User" -password "pw" function Add-FtpFolderWithFilesRecursive($sourceFolder, $destinationFolder, $userName, $password) { Add-FtpFolderWithFiles -sourceFolder $sourceFolder -destinationFolder $destinationFolder -userName $userName -password $password $subDirectories = Get-ChildItem $sourceFolder -Directory $fromUri = new-object System.Uri($sourceFolder) foreach($subDirectory in $subDirectories) { $toUri = new-object System.Uri($subDirectory.FullName) $relativeUrl = $fromUri.MakeRelativeUri($toUri) $relativePath = [System.Uri]::UnescapeDataString($relativeUrl.ToString()) $lastFolder = $relativePath.Substring($relativePath.LastIndexOf("/")+1) Add-FtpFolderWithFilesRecursive -sourceFolder $subDirectory.FullName -destinationFolder "$destinationFolder/$lastFolder" -userName $userName -password $password } }
quelle
ReadAllBytes
liest die gesamte Datei in den Speicher. Das wird bei großen Dateien nicht funktionieren. Und es ist selbst für mittelgroße Dateien ineffizient.Hier ist meine super coole Version, WEIL ES EINE PROGRESS BAR HAT :-)
Das ist eine völlig nutzlose Funktion, ich weiß, aber sie sieht immer noch cool aus \ m / \ m /
$webclient = New-Object System.Net.WebClient Register-ObjectEvent -InputObject $webclient -EventName "UploadProgressChanged" -Action { Write-Progress -Activity "Upload progress..." -Status "Uploading" -PercentComplete $EventArgs.ProgressPercentage } > $null $File = "filename.zip" $ftp = "ftp://user:password@server/filename.zip" $uri = New-Object System.Uri($ftp) try{ $webclient.UploadFileAsync($uri, $File) } catch [Net.WebException] { Write-Host $_.Exception.ToString() -foregroundcolor red } while ($webclient.IsBusy) { continue }
PS. Hilft sehr, wenn ich mich frage: "Hat es nicht mehr funktioniert oder ist es nur meine langsame ASDL-Verbindung?"
quelle
Sie können einfach das Hochladen von Dateien über PowerShell wie folgt durchführen. Das vollständige Projekt finden Sie auf Github unter https://github.com/edouardkombo/PowerShellFtp
#Directory where to find pictures to upload $Dir= 'c:\fff\medias\' #Directory where to save uploaded pictures $saveDir = 'c:\fff\save\' #ftp server params $ftp = 'ftp://10.0.1.11:21/' $user = 'user' $pass = 'pass' #Connect to ftp webclient $webclient = New-Object System.Net.WebClient $webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass) #Initialize var for infinite loop $i=0 #Infinite loop while($i -eq 0){ #Pause 1 seconde before continue Start-Sleep -sec 1 #Search for pictures in directory foreach($item in (dir $Dir "*.jpg")) { #Set default network status to 1 $onNetwork = "1" #Get picture creation dateTime... $pictureDateTime = (Get-ChildItem $item.fullName).CreationTime #Convert dateTime to timeStamp $pictureTimeStamp = (Get-Date $pictureDateTime).ToFileTime() #Get actual timeStamp $timeStamp = (Get-Date).ToFileTime() #Get picture lifeTime $pictureLifeTime = $timeStamp - $pictureTimeStamp #We only treat pictures that are fully written on the disk #So, we put a 2 second delay to ensure even big pictures have been fully wirtten in the disk if($pictureLifeTime -gt "2") { #If upload fails, we set network status at 0 try{ $uri = New-Object System.Uri($ftp+$item.Name) $webclient.UploadFile($uri, $item.FullName) } catch [Exception] { $onNetwork = "0" write-host $_.Exception.Message; } #If upload succeeded, we do further actions if($onNetwork -eq "1"){ "Copying $item..." Copy-Item -path $item.fullName -destination $saveDir$item "Deleting $item..." Remove-Item $item.fullName } } } }
quelle
Die Lösung von Goyuix funktioniert hervorragend, aber wie dargestellt wird folgende Fehlermeldung angezeigt : "Der angeforderte FTP-Befehl wird bei Verwendung des HTTP-Proxys nicht unterstützt."
Das Hinzufügen dieser Zeile nach dem
$ftp.UsePassive = $true
Beheben des Problems für mich:$ftp.Proxy = $null;
quelle
Sie können diese Funktion verwenden:
function SendByFTP { param ( $userFTP = "anonymous", $passFTP = "anonymous", [Parameter(Mandatory=$True)]$serverFTP, [Parameter(Mandatory=$True)]$localFile, [Parameter(Mandatory=$True)]$remotePath ) if(Test-Path $localFile){ $remoteFile = $localFile.Split("\")[-1] $remotePath = Join-Path -Path $remotePath -ChildPath $remoteFile $ftpAddr = "ftp://${userFTP}:${passFTP}@${serverFTP}/$remotePath" $browser = New-Object System.Net.WebClient $url = New-Object System.Uri($ftpAddr) $browser.UploadFile($url, $localFile) } else{ Return "Unable to find $localFile" } }
Diese Funktion sendet die angegebene Datei per FTP . Sie müssen die Funktion mit folgenden Parametern aufrufen:
Zum Beispiel :
SendByFTP -userFTP "USERNAME" -passFTP "PASSWORD" -serverFTP "MYSERVER" -localFile "toto.zip" -remotePath "path/on/the/FTP/"
quelle
Join-Path
URL auf diese Weise nicht verwenden .Join-Path
Verwendet standardmäßig Backslashes, während URL Schrägstriche verwendet. + Sie müssen auch URL-codierenuserFTP
undpassFTP
.