Reputation: 11
So I have a powershell script which downloads a a set of files one after another using a foreach-object loop (and System.Net.WebClient). From time to time I get a 404 error from the source URL for a particular file. The error is non-termninating so the script moves on when encountering this type of error. The issue is that the fileset needs to be downloaded as a set and is no good unless all files are available. So what I need to do is have the script pause and retry the download if it encounters a 404 error. I am having trouble figuring out how best to have this happen. Here is the code I am using for the download. Originally it just did this:
Get-Content $shaFile | Foreach-Object { ($_ -split " ", 2)[0] } |
Where-Object { ($adfs.$v.iniFile,$shaFile -NotContains $_) -and (Is-Match $_) } | Foreach-Object {
#$null=Download-File $w $_ $dir
So this downloads the files properly....unless I get some type of error like a 404. What I want to do is have it pick the error and then try and download the missed file, and keep trying until its downloaded. Typically this seems to be caused by a timing issue whereby I am trying to download a file the source URL is still publishing (copying and is not yet available). So if I can just detect the error and keep trying to download the file until downloaded as the source URL will eventually publish it. What I came up with is below:
Get-Content $shaFile | Foreach-Object { ($_ -split " ", 2)[0] } |
Where-Object { ($adfs.$v.iniFile,$shaFile -NotContains $_) -and (Is-Match $_) } | Foreach-Object {
try {
$null=Download-File $w $_ $dir
}
catch {
sleep 60
$null=Download-File $w $_ $dir
"Re-downloading missed file"
}
}
So I think this will have the script try again in a minute if it encounters an error. Thats fine I guess but I wanted to actually try and check for when the file is actually downloaded before moving on. So like some kind of while loop that says if $_ does not exist in destination, keep trying to download it until it does. In the above code I am calling a function called "Download-file" and a function "Is-Match". Download file uses System.Net.WebClient to download files from a website.
I thought maybe the following might work but am not sure its the best way to handle this:
Get-Content $shaFile | Foreach-Object { ($_ -split " ", 2)[0] } |
Where-Object { ($adfs.$v.iniFile,$shaFile -NotContains $_) -and (Is-Match $_) } | Foreach-Object {
do{
$Failed = $false
Try{
$null=Download-File $w $_ $dir
}
catch { $Failed = $true }
} while ($Failed)
Or perhaps I could do the following
Get-Content $shaFile | Foreach-Object { ($_ -split " ", 2)[0] } |
Where-Object { ($adfs.$v.iniFile,$shaFile -NotContains $_) -and (Is-Match $_) } | Foreach-Object {
Try{
$null=Download-File $w $_ $dir
}
catch {
while ($error){
Start-Sleep -s 60
$null=Download-File $w $_ $dir
}
}
I can test the code but I cannot test for the error very easily as most times the files are all there. Anyway I would appreciate any help here. Thanks in advance.
Upvotes: 1
Views: 905
Reputation: 356
I would try something like this. It assumes that the object returned for Download-File is null if the download fails - you'll have to check how it actually behaves. To simulate a failed download, you could re-write the returned object from Download-File to $null.
$maxRetries = 5
$retryWaitSeconds = 60
Get-Content $shaFile | Foreach-Object { ($_ -split " ", 2)[0] } |
Where-Object { ($adfs.$v.iniFile,$shaFile -NotContains $_) -and (Is-Match $_) } | Foreach-Object {
do {
$file = Download-File $w $_ $dir
#force the file download to fail 3 times for testing
foreach ($i in 1..3) {
$file = $null
}
#sleep if the file download failed.
if ($file -eq $null) {
start-sleep $retryWaitSeconds
}
}
while (($file -eq $null) -and ($retryCount -le $maxRetries)) #limit the maximum number of retries in case download will never succeed.
}
Upvotes: 1