Подтвердить что ты не робот

Загружать файлы с помощью FTP с помощью PowerShell

Я хочу использовать PowerShell для передачи файлов с FTP на анонимный FTP-сервер. Я бы не использовал никаких дополнительных пакетов. Как?

Не должно быть опасений, что script зависает или падает.

4b9b3361

Ответ 1

Я не уверен, что вы можете на 100% устранить ошибки script из-за того, что вы не висели или не рушились, поскольку есть вещи вне вашего контроля (что, если сервер теряет мощность в середине загрузки?), но это должно обеспечить прочную основу для начала:

# 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","[email protected]")
$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()

Ответ 2

Есть и другие способы. Я использовал следующий скрипт:

$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);

И вы можете запустить скрипт для утилиты командной строки Windows FTP, используя следующую команду

ftp -s:script.txt 

(Проверьте эту статью)

На этот вопрос также отвечает следующий вопрос: Как создать сценарий загрузки и выгрузки по FTP?

Ответ 3

Я не собираюсь утверждать, что это более элегантно, чем решение с высоким разрешением... но это классно (ну, по крайней мере, в моем уме 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

Как вы можете видеть, он использует этот dinky встроенный FTP-клиент Windows. Гораздо короче и прямолинейно. Да, я действительно использовал это, и он работает!

Ответ 4

Недавно я написал для powershell несколько функций для связи с FTP, см. Https://github.com/AstralisSomnium/PowerShell-No-Library-Just-Functions/blob/master/FTPModule.ps1. Вторая функция ниже, вы можете отправить всю локальную папку на FTP. В модуле есть четные функции для рекурсивного удаления/добавления/чтения папок и файлов.

#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
}

}

Ответ 5

Самый простой способ

Самый простой способ загрузки двоичного файла на FTP-сервер с помощью PowerShell - это использование 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")

Расширенные настройки

Если вам нужен больший контроль, который WebClient не предлагает (например, шифрование TLS/SSL и т.д.), Используйте FtpWebRequest. Простой способ - просто скопировать FileStream в поток 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 

$fileStream = [System.IO.File]::OpenRead("C:\local\path\file.zip")
$ftpStream = $request.GetRequestStream()

$fileStream.CopyTo($ftpStream)

$ftpStream.Dispose()
$fileStream.Dispose()

Мониторинг прогресса

Если вам нужно отслеживать ход загрузки, вы должны скопировать содержимое по частям:

$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()

Загрузка папки

Если вы хотите загрузить все файлы из папки, см.
PowerShell Script для загрузки всей папки на FTP

Ответ 6

Здесь моя супер классная версия ПОТОМУ ЧТО ЭТО БУДЕТ ПРОГРЕСС: -)

Это совершенно бесполезная функция, я знаю, но она по-прежнему выглядит круто \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:[email protected]/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. Помогает много, когда мне интересно, "он прекратил работать, или это просто мое медленное соединение ASDL?"

Ответ 7

Решение Goyuix отлично работает, но как представлено, он дает мне эту ошибку: "Запрошенная команда FTP не поддерживается при использовании прокси-сервера HTTP".

Добавление этой строки после $ftp.UsePassive = $true устраняет проблему для меня:

$ftp.Proxy = $null;

Ответ 8

Вы можете просто обрабатывать загрузки файлов через PowerShell, например. Полный проект доступен в Github здесь 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
            }


        }  
    }
}   

Ответ 9

Вы можете использовать эту функцию:

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"
    }
}

Эта функция отправляет указанный файл по FTP. Вы должны вызвать функцию с этими параметрами:

  • userFTP = "анонимный" по умолчанию или ваше имя пользователя
  • passFTP = "анонимный" по умолчанию или ваш пароль
  • serverFTP = IP-адрес FTP-сервера
  • localFile = Файл для отправки
  • remotePath = путь на FTP-сервере

Например:

SendByFTP -userFTP "USERNAME" -passFTP "PASSWORD" -serverFTP "MYSERVER" -localFile "toto.zip" -remotePath "path/on/the/FTP/"