簡體   English   中英

如何在不寫入文件的情況下壓縮 stream 並將其上傳到 Azure Blob 存儲?

[英]How do you compress a stream and upload it to Azure Blob Storage without writing to a file?

我在 ASP.NET Core 中編寫了一個Post方法來壓縮請求正文並將其上傳到 Azure Blob 存儲。 該方法采用以下參數:

public async Task<IActionResult> Post([FromHeader] string AssignmentId)

然后設置各種字符串,包括獲取存儲的連接字符串:

string fileName = $"{AssignmentId}.gz";
string compressedFilePath = Path.Combine(hostEnvironment.ContentRootPath, $"Test JSONs/{fileName}");
string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");

我初始化BlobClient

BlobClient blobClient = new BlobClient(connectionString, "assignments", fileName);

然后我創建一個文件,並使用GZipStream將請求的主體 stream 壓縮到文件中:

using (FileStream compressedFileStream = System.IO.File.Create(compressedFilePath))
{
    using GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress);
    using Stream bodyStream = HttpContext.Request.Body;
    await bodyStream.CopyToAsync(compressionStream);
}

最后,我閱讀了我剛剛編寫並使用FileStream上傳的文件:

using (FileStream fileStream = System.IO.File.OpenRead(compressedFilePath))
{
    await blobClient.UploadAsync(fileStream);
}

這個解決方案有效,但我擔心文件的不斷讀寫,就速度而言。 我嘗試使用傳遞給GZipStreamMemoryStream ,但是當文件應該為 1KB+ 時,它最終只上傳了 10B 文件。

我很感激任何建議。

這是完整的方法:

public async Task<IActionResult> Post([FromHeader] string AssignmentId)
{
    string fileName = $"{AssignmentId}.gz";
    string compressedFilePath = Path.Combine(hostEnvironment.ContentRootPath, $"Test JSONs/{fileName}");
    string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");

    BlobClient blobClient = new BlobClient(connectionString, "assignments", fileName);
    
    using (FileStream compressedFileStream = System.IO.File.Create(compressedFilePath))
    {
        using GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress);
        using Stream bodyStream = HttpContext.Request.Body;
        await bodyStream.CopyToAsync(compressionStream);
    }

    using (FileStream fileStream = System.IO.File.OpenRead(compressedFilePath))
    {
        await blobClient.UploadAsync(fileStream);
    }
    
    return Ok();
}

I eventually solved this by both leaving the compression stream open, and by resetting the position of the memory stream the compression stream is writing to (thanks to @MitchWheat.).

using MemoryStream memoryStream = new MemoryStream() ;
using (Stream bodyStream = HttpContext.Request.Body)
{
    using (GZipStream compressionStream = new GZipStream(memoryStream, 
    CompressionMode.Compress, true))
    {
        await bodyStream.CopyToAsync(compressionStream);
    }
}
memoryStream.Position = 0;

await blobClient.UploadAsync(memoryStream, overwrite: true);

Azure 存儲庫提供了一個基於推送的 stream 來上傳適用於壓縮的內容。

const int PageSize = 1024 * 1024; // 1 MB
using var sourceFile = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
using var destinationStream = await blobClient.OpenWriteAsync(overwrite: true, new() { BufferSize = PageSize }, cancellationToken);
using var compressedContent = new GZipStream(destinationStream, CompressionMode.Compress, leaveOpen: true);
await sourceFile.CopyToAsync(compressedContent, cancellationToken);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM