I have a webcam which uploads a captured image every two minutes to a website, just replacing the last one. I made a Powershell-script that goes in and downloads that image every two minutes and everything works fine. But sometimes it gets out of sync because the upload from the webcam uses 3G data-connection and I guess sometimes it´s to slow to upload exactly with two minutes between every file. So my script sometimes download a half image, when the upload is still in progress from the webcam.
Is there a way to make sure the webcam image is completly uploaded before I downloads it?
I tried to make it look for the filesize in the downloaded image and if its below a certain size it would be deleted right away and keep my downloadfolder clean from "garbage", but since the images sometimes are different size its not a very reliable method to do it.
So, how can I make the script check if the image is fully uploaded before it downloads it?
Here is my code now
$imgNum = 0
while ($true)
{
cls
$storageDir = "C:\Temp\Norberg"
$url = "http://www.norberg.se/images/webcam/bild/image.jpg"
$file = "$storageDir\norberg_$(Get-Date -Format "yyyyMMdd-HHmmss").jpg"
Write-Host "---------------------------------------------------------------" -Fore "yellow"
Write-Host " Location: Norberg - Mimerlaven" -Fore "yellow"
Write-Host " Input: $url" -Fore "yellow"
Write-Host " Output: $file" -Fore "yellow"
Write-Host "---------------------------------------------------------------" -Fore "yellow"
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile($url,$file)
$numUp = ++$imgNum
$lastFile = gci $storageDir | sort LastWriteTime | select -last 1
$lastFileSize = $lastFile.Length
if ($lastFileSize -lt 100kb) {remove-item $storageDir"\"$lastFile}
Write-Host "Number of pictures taken: $imgNum" -Fore "yellow"
Write-Host "Last file size: "($lastFile.Length / 1KB) Kb -fore "yellow"
$x = 2*60
$length = $x / 100
while($x -gt 0) {
$min = [int](([string]($x/60)).split('.')[0])
$text = " " + $min + " minutes " + ($x % 60) + " seconds left"
Write-Progress "Tar nästa bild om..." -status $text -perc ($x/$length)
start-sleep -s 1
$x--
}
}
The purpose of this script is I want to capture images to make a timelapse-video, initially 24 hours but in the future i´m thinking one or two images per day and make a whole-year-timelapse to see the seasons change.
Here is my final version. Convert every image to HEX and look for the EndOfFile-value for .jpg-files. Delete if EOF not found.
# Limit for how many days the images should be saved (Saving the last 7 days, deleting anything older).
$limit = (Get-Date).AddDays(-7)
# Reset the counter showing how many images have been downloaded since the script started
$imgNum = 0
# Reset the counter showing how many images have been deleted since the script started, older than $limit days
$DelImgNum = 0
# Where to save the imgages
$storageDir = "C:\Temp\webcam"
# Which image to download
$url = "http://www.norberg.se/webdav/files/Webbkamera/image.jpg"
# Two functions that read the downloaded image as HEX
function Join-String {
begin { $sb = New-Object System.Text.StringBuilder }
process { $sb.Append($_) | Out-Null }
end { $sb.ToString() }
}
function Format-HexString {
param([string[]]$path)
gc -en byte $path -Tail 10000 | % { '{0:X2}' -f $_ } | Join-String
}
$TestStorageDir = Test-Path $storageDir
if ($TestStorageDir -eq $False) {
Write-Host ""
Write-Host "[ERROR ] The folder you chose to use does not exist !!!" -fore "Red"
Write-Host ""
Return
}
# Starting the download
while ($true) {
cls
# Naming the downloaded files
$file = "$storageDir\norberg_$(Get-Date -Format "yyyyMMdd-HHmmss").jpg"
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host ""
Write-Host "---------------------------------------------------------------" -Fore "yellow"
Write-Host " Location: Norberg - Mimerlaven" -Fore "yellow"
Write-Host " URL: $url" -Fore "yellow"
Write-Host " Saved as: $file" -Fore "yellow"
Write-Host "---------------------------------------------------------------" -Fore "yellow"
$webclient = New-Object System.Net.WebClient
$webclient.DownloadFile($url,$file)
++$imgNum
$lastFile = gci $storageDir | sort LastWriteTime | select -last 1
$lastFileSize = $lastFile.Length
# Reading the last downloaded image as HEX
$imgEOF = Format-HexString $storageDir"\"$lastFile
# Trim all the zeros from the end of the file
$hex = $imgEOF.TrimEnd("0")
# Checking the last 4 bits of the file, looking for "FFD9" (EOF/End of File for .jpg file format). If FFD9 exist, save image, if not delete it.
# This is to make sure the image is totally upploaded from the webcam to the server where it´s beeing downloaded from.
# Earlier i experiensed problems where the scrip would download only a half image and it would be corrupt
# This makes sure the image is complete before saving it.
if ($lastFileSize -gt 0) {
$check = $hex.substring($hex.length - 4, 4)
if ($check -ne "FFD9")
{
#remove-item $storageDir"\"$lastFile
Write-Host "Number of pictures saved: $imgNum" -ForegroundColor Yellow
Write-Host "Number of pictures deleted: $DelImgNum" -ForegroundColor Yellow
Write-Host "Last 4 bits of image: $check" -ForegroundColor Yellow -NoNewline
Write-Host " DELETED (image was corrupt)" -ForegroundColor Red
++$DelImgNum
} else
{
Write-Host "Number of pictures saved: $imgNum"-ForegroundColor Yellow
Write-Host "Number of pictures deleted: $DelImgNum" -ForegroundColor Yellow
Write-Host "Last 4 bits of image: $check" -ForegroundColor Yellow
}
} else {
Write-Host " - Picture is 0kb, deleted it" -ForegroundColor Red
Remove-Item $storageDir"\"$lastFile
++$DelImgNum
}
# Deleting pictures older than x days, see variable $limit
Get-ChildItem -Path $storageDir -Recurse -Force | Where-Object { $_.CreationTime -lt $limit } | Remove-Item -Force
# Timer pausing the script before downloading the next picture, now set to 2x60 seconds = 2 minutes.
$x = 2*60
$length = $x / 100
while($x -gt 0) {
$min = [int](([string]($x/60)).split('.')[0])
$text = " " + $min + " minutes " + ($x % 60) + " seconds"
Write-Progress "Downloading next image in..." -status $text -perc ($x/$length)
start-sleep -s 1
$x--
}
}