@Julien Ferreira Apologies for the late reply. Welcome to Microsoft Q&A Forum, Thank you for posting your query here!
Could you please try updating the DownloadCollection
class to stream the zip archive as it's being created, instead of first archiving all the blobs in memory and then returning the zip:
The key changes I have done are below:
- Instead of returning a
FileStreamResult
, we write directly to the response stream usingresponse.BodyWriter.AsStream()
. - We pass the response stream to the
GetZipArchive
method, which creates theZipArchive
directly on the response stream and writes each blob to it as it's being read.
public class DownloadCollection
{
private readonly string _connectionString;
private BlobServiceClient _storageService;
public DownloadCollection()
{
_connectionString = Environment.GetEnvironmentVariable("STORAGE_ACCOUNT_CONNECTION_STRING");
}
[FunctionName("DownloadCollection")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "download-collection/{id:alpha}")] HttpRequest req, string? id,
ILogger log)
{
log.LogInformation("Download Collection C# HTTP trigger function processed a request.");
try
{
_storageService = StorageService.Account(_connectionString);
BlobDetails blobDetails = JsonSerializer.Deserialize<BlobDetails>(@"{ ""InputBlobName"": ""wetweak-welcome-pack"", ""InputBlobFileExtension"": ""zip"", ""SourceContainer"":""welcome-pack""}");
BlobDetails[] blobs = new BlobDetails[] {
JsonSerializer.Deserialize<BlobDetails>(@"{ ""InputBlobName"": ""0f8085be-f3dd-4c8e-8e08-5e616fcbe815"", ""InputBlobFileExtension"": ""mp3"", ""SourceContainer"":""staging-sounds""}"),
JsonSerializer.Deserialize<BlobDetails>(@"{ ""InputBlobName"": ""1a7d3c94-0c88-4f4c-beee-14e344232f50"", ""InputBlobFileExtension"": ""fxp"", ""SourceContainer"":""staging-sounds""}"),
JsonSerializer.Deserialize<BlobDetails>(@"{ ""InputBlobName"": ""1f72e057-1ac1-47aa-b0d9-8186af0c2fe0"", ""InputBlobFileExtension"": ""fxp"", ""SourceContainer"":""staging-sounds""}"),
JsonSerializer.Deserialize<BlobDetails>(@"{ ""InputBlobName"": ""40e518e9-7c0a-413b-92e9-c91e20b20643"", ""InputBlobFileExtension"": ""fxp"", ""SourceContainer"":""staging-sounds""}"),
JsonSerializer.Deserialize<BlobDetails>(@"{ ""InputBlobName"": ""565908b1-f4f3-4969-aa50-bdffc08e228c"", ""InputBlobFileExtension"": ""fxp"", ""SourceContainer"":""staging-sounds""}")
};
var response = req.HttpContext.Response;
response.ContentType = "application/octet-stream";
response.Headers.Add("Content-Disposition", "attachment; filename=\"collection.zip\"");
await GetZipArchive(blobs, _storageService, log, response.BodyWriter.AsStream());
return new OkResult();
}
catch (Exception ex)
{
log.LogInformation("Error into ArchiveToZip() " + ex.Message);
throw;
}
}
public async static Task GetZipArchive(BlobDetails[] blobs, BlobServiceClient _storageService, ILogger _logger, Stream outputStream)
{
using (var archive = new ZipArchive(outputStream, ZipArchiveMode.Create, true))
{
foreach (var blobDetails in blobs)
{
var memoryStreamBlob = new StreamBlobs(_storageService, blobDetails, _logger);
//we get the blob that we need and we add it to a stream
var blobAsStream = memoryStreamBlob.ReadBlobAsStream(blobDetails, _logger);
var zipArchiveEntry = archive.CreateEntry(blobDetails.InputBlobName, CompressionLevel.Fastest);
using var zipStream = zipArchiveEntry.Open();
await blobAsStream.CopyToAsync(zipStream);
}
}
}
}
Hope this helps.
** Please do not forget to "Accept the answer” and “up-vote” wherever the information provided helps you, this can be beneficial to other community members.