首页 文章

使用PowerShell使用FTP上载文件

提问于
浏览
64

我想使用PowerShell将文件与FTP一起传输到匿名FTP服务器 . 我不会使用任何额外的包 . 怎么样?

脚本必须没有挂起或崩溃的风险 .

8 回答

  • 40

    还有其他一些方法 . 我使用了以下脚本:

    $File = "D:\Dev\somefilename.zip";
    $ftp = "ftp://username:password@example.com/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
    

    (查看this article

    关于SO的以下问题也回答了这个问题:How to script FTP upload and download?

  • 5

    我不会声称这比最高投票的解决方案更优雅......但这很酷(嗯,至少在我看来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
    

    如您所见,它使用了那个极简的内置Windows FTP客户端 . 更短更直接 . 是的,我实际上已经使用了它,它的确有效!

  • 2

    我不确定你是否可以100%防止脚本不挂起或崩溃,因为有些东西无法控制(如果服务器在上传中途失去了怎么办?) - 但这应该为你开始提供坚实的基础:

    # 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()
    
  • 2

    这是我的超酷版本,因为它有一个进步条:-)

    我知道,这是一个完全无用的功能,但它看起来仍然很酷\ 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 . 当我想知道“它是否停止工作,还是仅仅是我的ASDL连接缓慢?”时,有很多帮助?

  • 3

    Goyuix's solution效果很好,但是如上所述它给了我这个错误:"The requested FTP command is not supported when using HTTP proxy."

    $ftp.UsePassive = $true 之后添加此行为我解决了问题:

    $ftp.Proxy = $null;
    
  • 75

    使用PowerShell将二进制文件上传到FTP服务器的最简单方法是使用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 . 简单的方法是使用Stream.CopyToFileStream 复制到FTP流:

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

    我最近为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
    }
    

    }

  • 25

    您可以通过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
                }
    
    
            }  
        }
    }
    

相关问题