kofifus
kofifus

Reputation: 19295

Download and unzip file asynchronically

So far here's my code:

async Task<bool> HttpDownloadAndUnzip(string requestUri, string directoryToUnzip) 
{
  using var response = await new HttpClient().GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead);
  if (!response.IsSuccessStatusCode) return false;

  using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
  using var zip = new ZipArchive(streamToReadFrom); // Blocks! 

  zip.ExtractToDirectory(directoryToUnzip);
  return true;
}

What I see tracing with the debugger is that the ZipArchive constructor blocks until the entire file is downloaded from the URI

This makes the bulk of the operation synchronous whereas I want both downloading and unzipping to be asynchronous.

What is the solution here ? how to make unzipping async ?

PS would be nice to have ExtractToDirectory async as well

Upvotes: 2

Views: 1659

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456577

The ZipArchive support in .NET only has some very basic asynchronous support.

You could download the stream into memory asynchronously (by removing HttpCompletionOption.ResponseHeadersRead), and then do the unzipping:

async Task<bool> HttpDownloadAndUnzip(string requestUri, string directoryToUnzip) 
{
  using var response = await new HttpClient().GetAsync(requestUri);
  if (!response.IsSuccessStatusCode) return false;

  using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
  using var zip = new ZipArchive(streamToReadFrom);
  zip.ExtractToDirectory(directoryToUnzip);
  return true;
}

I'm not aware of any asynchronous implementations of ExtractToDirectory in the BCL or any .NET library.

Upvotes: 3

Serj Sagan
Serj Sagan

Reputation: 30208

The most simple solution is to wrap your blocking code in

await Task.Run(() =>
{
    // blocking code goes here
});

It will still wait for the entire file to download before being viewable, but it will be async.

To be able to view the contents of a partially downloaded file would require you to write your own unzipper.

Upvotes: 1

Related Questions