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 小时,但在未来我想每天一到两张图像,并制作一整年的延时视频以查看季节变化。

4

3 回答 3

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)

** 代码未经测试 **

于 2013-11-08T14:50:37.430 回答
0

这是我的最终版本。将每个图像转换为 HEX 并查找 .jpg 文件的 EndOfFile 值。如果没有找到 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--
}
}
于 2017-04-06T06:55:34.613 回答
-1
        WebClient client = new WebClient();

        byte[] image_as_a_Byte = client.DownloadData("Your URL");

        Image pic = (Bitmap)((new ImageConverter()).ConvertFrom(image_as_a_Byte));
        pic.Save("yourImage.jpeg", ImageFormat.Jpeg);
于 2019-11-04T10:16:45.177 回答