2013-10-17 101 views
2

我有一個網絡攝像頭,每兩分鐘上傳一個捕獲的圖像到一個網站,只需更換最後一個。我製作了一個Powershell腳本,每兩分鐘下載一次這個映像,一切正常。但有時它會不同步,因爲從網絡攝像頭上傳使用3G數據連接,我想有時會在每個文件之間用兩分鐘時間完全上傳。 所以我的腳本有時會從網絡攝像頭上傳正在下載的一半圖片。從網址/網絡攝像頭保存圖像

有沒有辦法確保攝像頭圖像在我下載之前完整上傳?

我試圖讓它在下載的圖像中查找文件大小,如果它的大小低於一定的大小,它會立即刪除,並保持我的下載文件夾乾淨的「垃圾」,但由於圖像有時是不同的大小,它不是一個非常可靠的方法來做到這一點。

那麼,如何在腳本下載之前檢查腳本是否完全上傳?

這是現在

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

我的代碼,這個腳本的目的是我想拍攝圖像做出延時視頻,最初24小時但在未來i'm思考每一個或兩個圖像一天,並製作一整年的時間來看季節的變化。

+0

[可能的複製?](http://stackoverflow.com/questions/9394629/how-to-check-if-file-is-being-used-by-another-process-powershell) – nimizen

+0

如何你的意思是? 我還應該提到我沒有訪問Web服務器,所以我不能在該機器上運行任何檢查,以確定當前是否有任何進程正在使用該文件。 – Frigol33t

+0

所以你認爲攝像頭是一個「黑匣子」,對吧? 如果沒有,我建議讓你的攝像頭上傳到你的網站和你的電腦。 你可以檢查JPEG的有效性,但我沒有關於它的信息。 JPEG上有EOF嗎? – Dreami

回答

0

這是我的最終版本。將每個圖像轉換爲HEX並查找.jpg文件的EndOfFile-value。如果沒有找到EOF,請刪除。

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

您可以添加下面的代碼來確定文件的大小,暫停然後再次檢查大小並比較這兩個值。重複,直到你得到兩個文件大小相同的檢查,表明它已經完成上傳。

Function GetFileSize { 
    Param(
     [parameter(Mandatory=$true)] 
     [System.Net.WebClient] 
     $Client, 

     [parameter(Mandatory=$true)] 
     [string] 
     $Url 
    ) 
    $Client.OpenRead($url) | Out-Null 
    $Client.ResponseHeaders["Content-Length"] 
} 

do { 
    $filesize1 = GetFileSize -Client $webclient -Url $url 
    Start-Sleep -s 10 
    $filesize2 = GetFileSize -Client $webclient -Url $url 
    $difference = $filesize1 - $filesize2 
} 
until($difference -eq 0) 

**未測試的代碼**