Powershell - gzip большой файл и загрузка в s3 с использованием потока - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь сжать некоторые CSV-файлы с помощью gzip и затем загрузить их на S3. Мне нужно использовать потоки для сжатия и загрузки, потому что файлы могут быть очень большими, и я не хочу записывать файл обратно на диск перед загрузкой в ​​s3. Я новичок в использовании потоков в Powershell и изо всех сил пытаюсь выяснить проблему.

Это то, что у меня есть, но я не могу заставить его работать. Он загружает очень маленький файл gzip, который показывает мой оригинальный файл внутри, но я не могу извлечь его - я получаю ошибку «Неожиданный конец данных». Я считаю, что это не завершение потока gzip или что-то в этом роде. Если я удаляю команды "gzip" и просто записываю inputFileStream в S3, то он работает для загрузки несжатого файла, поэтому я знаю, что загрузка S3 с использованием потока работает.
Кроме того, я использую "CopyTo", который я Вера принесет весь файл в память, которую я тоже не хочу (дайте мне знать, если я не прав с этим мнением).

$sourcePath =  "c:\temp\myfile.csv"
$bucketName = "mybucket"
$s3Key = "staging/compress_test/"

$fileInfo = Get-Item -Path $sourcePath
$destPath = "$s3Key$($fileInfo.Name).gz"

$outputMemoryStream = New-Object System.IO.MemoryStream 
$gzipStream = New-Object System.IO.Compression.GZipStream $outputMemoryStream, ([IO.Compression.CompressionMode]::Compress)

$inputFileStream = New-Object System.IO.FileStream $sourcePath, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
$inputFileStream.CopyTo($gzipStream)

Write-S3Object -BucketName $destBucket -Key $destPath -Stream $outputMemoryStream -ProfileName Dev -Region us-east-1

$inputFileStream.Close()
$outputMemoryStream.Close()

ОБНОВЛЕНИЕ: Спасибо @FoxDeploy. Я получил по крайней мере, загрузку файла сейчас. Мне нужно было закрыть поток gzip перед записью в S3, чтобы gzip завершил работу. Но, как я подозревал, «CopyTo» приводит к сжатию файла и его сохранению в памяти, а затем загружается на S3. Я бы хотел, чтобы он передавался на S3, поскольку он сжимает, чтобы уменьшить загрузку памяти, если это возможно.
Вот текущий рабочий код:

$sourcePath =  "c:\temp\myfile.csv"
$bucketName = "mybucket"
$s3Key = "staging/compress_test/"

$fileInfo = Get-Item -Path $sourcePath
$destPath = "$s3Key$($fileInfo.Name).gz"

$outputMemoryStream = New-Object System.IO.MemoryStream 
$gzipStream = New-Object System.IO.Compression.GZipStream $outputMemoryStream, ([IO.Compression.CompressionMode]::Compress), true

$inputFileStream = New-Object System.IO.FileStream $sourcePath, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
$inputFileStream.CopyTo($gzipStream)

$gzipStream.Close()

Write-S3Object -BucketName $bucketName -Key $destPath -Stream $outputMemoryStream -ProfileName Dev -Region us-east-1

$inputFileStream.Close()
$outputMemoryStream.Close()
...