如果文件已使用powershell更改,我该如何下载文件

时间:2014-10-23 17:26:05

标签: powershell

我正在使用这个简单的函数下载文件:

function DownloadFile([string]$url, [string]$file)
{
    $clnt = new-object System.Net.WebClient
    Write-Host "Downloading from $url to $file " 
    $clnt.DownloadFile($url, $file)
}

它工作正常,但我使用的脚本调用它可以多次调用,目前可能意味着多次下载文件。

如果文件在本地不存在或者服务器版本较新(例如服务器上的LastModifiedDate大于本地LastModifiedDate),我如何修改该功能才能下载?

修改 这是我到目前为止所做的,似乎有效,但不希望有2次调用服务器。

function DownloadFile([string]$url, [string]$file)
{
    $downloadRequired = $true
    if ((test-path $file)) 
    {
        $localModified = (Get-Item $file).LastWriteTime 
        $webRequest = [System.Net.HttpWebRequest]::Create($url);
        $webRequest.Method = "HEAD";
        $webResponse = $webRequest.GetResponse()
        $remoteLastModified = ($webResponse.LastModified) -as [DateTime] 
        $webResponse.Close()

        if ($remoteLastModified -gt $localModified)
        {
            Write-Host "$file is out of date"
        }
        else
        {
            $downloadRequired = $false
        }

    }

    if ($downloadRequired)
    {
        $clnt = new-object System.Net.WebClient
        Write-Host "Downloading from $url to $file"
        $clnt.DownloadFile($url, $file)
    }
    else
    {
        Write-Host "$file is up to date."
    }
}

3 个答案:

答案 0 :(得分:7)

本周我一直在打这个,并想出了这个

# ----------------------------------------------------------------------------------------------
# download a file
# ----------------------------------------------------------------------------------------------
Function Download-File {
Param (
	[Parameter(Mandatory=$True)] [System.Uri]$uri,
	[Parameter(Mandatory=$True )] [string]$FilePath
)

#Make sure the destination directory exists
#System.IO.FileInfo works even if the file/dir doesn't exist, which is better then get-item which requires the file to exist
If (! ( Test-Path ([System.IO.FileInfo]$FilePath).DirectoryName ) ) { [void](New-Item ([System.IO.FileInfo]$FilePath).DirectoryName -force -type directory)}

#see if this file exists
if ( -not (Test-Path $FilePath) ) {
	#use simple download
	[void] (New-Object System.Net.WebClient).DownloadFile($uri.ToString(), $FilePath)
} else {
	try {
		#use HttpWebRequest to download file
		$webRequest = [System.Net.HttpWebRequest]::Create($uri);
		$webRequest.IfModifiedSince = ([System.IO.FileInfo]$FilePath).LastWriteTime
		$webRequest.Method = "GET";
		[System.Net.HttpWebResponse]$webResponse = $webRequest.GetResponse()

		#Read HTTP result from the $webResponse
		$stream = New-Object System.IO.StreamReader($webResponse.GetResponseStream())
		#Save to file
		$stream.ReadToEnd() | Set-Content -Path $FilePath -Force 

	} catch [System.Net.WebException] {
		#Check for a 304
		if ($_.Exception.Response.StatusCode -eq [System.Net.HttpStatusCode]::NotModified) {
			Write-Host "  $FilePath not modified, not downloading..."
		} else {
			#Unexpected error
			$Status = $_.Exception.Response.StatusCode
			$msg = $_.Exception
			Write-Host "  Error dowloading $FilePath, Status code: $Status - $msg"
		}
	}
}
}

答案 1 :(得分:1)

# If the local directory exists and it gets a response from the url,
# it checks the last modified date of the remote file. If the file
# already exists it compares the date of the file to the file from
# the url. If either the file doesn't exists or has a newer date, it
# downloads the file and modifies the file's date to match.

function download( $url, $dir, $file ) {
 if( Test-Path $dir -Ea 0 ) {
  $web = try { [System.Net.WebRequest]::Create("$url/$file").GetResponse() } catch [Net.WebException] {}
  if( $web.LastModified ) {
   $download = 0
   if(-Not(Test-Path "$dir\$file" -Ea 0)) { $download = 1 }
   elseif((gi "$dir\$file").LastWriteTime -ne $web.LastModified) { $download = 1 }
   if( $download ) {
    Invoke-WebRequest "$url/$file" -OutFile "$dir\$file" | Wait-Process
    (gi "$dir\$file").LastWriteTime = $web.LastModified
   }
   $web.Close()
  }
 }
}
download "https://website.com" "$env:systemdrive" "file.txt"

答案 2 :(得分:0)

最后修改的是HTTP响应标头。

试试这个:

$clnt.OpenRead($Url).Close();
$UrlLastModified = $clnt.ResponseHeaders["Last-Modified"];

如果它比您文件上的日期新,那么您的文件已经过时了。

远程服务器不必回复准确的日期或文件的实际上次修改日期,但很多人会这样做。

GetWebResponse()可能是更好的方法(或更正确的方式)。之后立即使用OpenRead()然后Close()会影响我的敏感度,但我可能会发疯。我主要从事数据库工作。