Powershell распаковать поток - PullRequest
0 голосов
/ 13 ноября 2018

Есть ли встроенный командлет или какой-либо другой состав, который позволил бы мне начать разархивировать поток файлов при загрузке каждого чанка?У меня есть сценарий PowerShell, который должен загрузить большой (10 ГБ) файл, и мне нужно подождать, пока это не будет сделано прямо сейчас, прежде чем он начнет расширяться ...

$wc = New-Object net.webclient
$wc.Downloadfile($appDataSnapshotUri, "%DataSnapshotFileName%.zip") # this can take some time

Expand-Archive -Path "%DataSnapshotFileName%.zip" -DestinationPath Run # so can this

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Чтобы расширить ответ Майка Твка, сценарий, чтобы сделать это с и без потока, и сравнить, сколько времени это займет:

$url = "yoururlhere"

function UnzipStream () {
    Write-Host "unzipping via stream"

    $stopwatch1 =  [system.diagnostics.stopwatch]::StartNew()


    Add-Type -Path ".\ICSharpCode.SharpZipLib.dll"

    $outFolder = "unzip-stream"

    $wc = [System.Net.WebClient]::new()

    $zipStream = $wc.OpenRead($url)

    $zipInputStream = [ICSharpCode.SharpZipLib.Zip.ZipInputStream]::New($zipStream)

    $zipEntry = $zipInputStream.GetNextEntry()

    while($zipEntry) {

    if (-Not($zipEntry.IsDirectory)) { 
    $fileName = $zipEntry.Name

    $buffer = New-Object byte[] 4096

    $filePath = "$pwd\$outFolder\$fileName"
    $parentPath = "$filePath\.."
    Write-Host $parentPath

    if (-Not (Test-Path $parentPath)) {
        New-Item -ItemType Directory $parentPath
    }

    $sw = [System.IO.File]::Create("$pwd\$outFolder\$fileName")

    [ICSharpCode.SharpZipLib.Core.StreamUtils]::Copy($zipInputStream, $sw, $buffer)

    $sw.Close()
    }

    $zipEntry = $zipInputStream.GetNextEntry()

    }

    $stopwatch1.Stop()

    Write-Host "extraction took $($stopWatch1.ElapsedMilliseconds) millis with stream"
}

function UnzipWithoutStream() {

    Write-Host "Extracting without stream"

    $stopwatch2 = [system.diagnostics.stopwatch]::StartNew()
    $outFolder2 = "unzip-normal"

    $wc2 = New-Object System.Net.WebClient
    $wc2.DownloadFile($url, "$pwd\download.zip")

    $of2 = New-Item -ItemType Directory $outFolder2

    Expand-Archive -Path "download.zip" -DestinationPath $of2.FullName

    $stopwatch2.Stop()

    Write-Host "extraction took $($stopWatch2.ElapsedMilliseconds) millis without stream"
}

UnzipStream
UnzipWithoutStream
0 голосов
/ 16 ноября 2018

ОК, получается, что для распаковки zip-файл не нужно загружать полностью, вы можете сжимать / распаковывать потоки.В .Net есть некоторые встроенные возможности сжатия потоков, но он не будет работать с zip-архивами.Для этого вы можете использовать библиотеку SharpZipLib:

Загрузить .nupckg из https://www.nuget.org/packages/SharpZipLib/ Извлечь файлы в любую папку.Вам понадобится ICSharpCode.SharpZipLib.dll из lib / net45

Ниже приведен упрощенный перевод их примера: https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples#unpack-a-zip-using-zipinputstream-eg-for-unseekable-input-streams

Add-Type -Path ".\ICSharpCode.SharpZipLib.dll"

$outFolder = ".\unzip"

$wc = [System.Net.WebClient]::new()

$zipStream = $wc.OpenRead("http://gitlab/test/test1/raw/master/sample.zip")

$zipInputStream = [ICSharpCode.SharpZipLib.Zip.ZipInputStream]::New($zipStream)

$zipEntry = $zipInputStream.GetNextEntry()

$fileName = $zipEntry.Name

$buffer = New-Object byte[] 4096

$sw = [System.IO.File]::Create("$outFolder\$fileName")

[ICSharpCode.SharpZipLib.Core.StreamUtils]::Copy($zipInputStream, $sw, $buffer)

$sw.Close()

Он будет извлекать только первую запись, которую вы можете добавитьцикл while, этот пример работает.

Вот фрагмент с циклом while для извлечения нескольких файлов (поместите его после $zipEntry = $zipInputStream.GetNextEntry() в приведенном выше примере):

While($zipEntry) {

$fileName = $zipEntry.Name

Write-Host $fileName

$buffer = New-Object byte[] 4096

$sw = [System.IO.File]::Create("$outFolder\$fileName")

[ICSharpCode.SharpZipLib.Core.StreamUtils]::Copy($zipInputStream, $sw, $buffer)

$sw.Close()

$zipEntry = $zipInputStream.GetNextEntry()

}

Редактировать

Вот что я нашел для работы ...

Add-Type -Path ".\ICSharpCode.SharpZipLib.dll"

$outFolder = "unzip"

$wc = [System.Net.WebClient]::new()

$zipStream = $wc.OpenRead("https://github.com/Esri/file-geodatabase-api/raw/master/FileGDB_API_1.5/FileGDB_API_1_5_VS2015.zip")

$zipInputStream = [ICSharpCode.SharpZipLib.Zip.ZipInputStream]::New($zipStream)

$zipEntry = $zipInputStream.GetNextEntry()

while($zipEntry) {

if (-Not($zipEntry.IsDirectory)) { 
  $fileName = $zipEntry.Name

  $buffer = New-Object byte[] 4096

  $filePath = "$pwd\$outFolder\$fileName"
  $parentPath = "$filePath\.."
  Write-Host $parentPath

  if (-Not (Test-Path $parentPath)) {
      New-Item -ItemType Directory $parentPath
  }

  $sw = [System.IO.File]::Create("$pwd\$outFolder\$fileName")

  [ICSharpCode.SharpZipLib.Core.StreamUtils]::Copy($zipInputStream, $sw, $buffer)
  $sw.Close()

}

$zipEntry = $zipInputStream.GetNextEntry()

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...