I am writing functionality for our web server which should download several files from other servers, and return them as a zip archive without compression.
How can I determine the final size of the ZIP archive if I know the sizes of all downloaded files?
This is the code which I am working on for the moment. The commented line caused corruption of the ZIP archive.
public void Download()
{
var urls = Request.Headers["URLS"].Split(';');
Task<WebResponse>[] responseTasks = urls
.Select(it =>
{
var request = WebRequest.Create(it);
return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse(null, null), request.EndGetResponse);
})
.ToArray();
Task.WaitAll(responseTasks);
var webResponses = responseTasks.Where(it => it.Exception == null).Select(it => it.Result);
var totalSize = webResponses.Sum(it => it.ContentLength + 32);
Response.ContentType = "application/zip";
Response.CacheControl = "Private";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
// Response.AddHeader("Content-Length", totalSize.ToString(CultureInfo.InvariantCulture));
var sortedResponses = webResponses.OrderBy(it => it.ContentLength);
var buffer = new byte[32 * 1024];
using (var zipOutput = new ZipOutputStream(Response.OutputStream))
{
zipOutput.SetLevel(0);
foreach (var response in sortedResponses)
{
var dataStream = response.GetResponseStream();
var ze = new ZipEntry(Guid.NewGuid().ToString() + ".jpg");
zipOutput.PutNextEntry(ze);
int read;
while ((read = dataStream.Read(buffer, 0, buffer.Length)) > 0)
{
zipOutput.Write(buffer, 0, read);
Response.Flush();
}
if (!Response.IsClientConnected)
{
break;
}
}
zipOutput.Finish();
}
Response.Flush();
Response.End();
}
I had the same problem and reading the ZIP-spec came up with the following solution:
zip_size = num_of_files * (30 + 16 + 46) + 2 * total_length_of_filenames + total_size_of_files + 22
with:
Local file header
Data descriptor
Central directory file header
End of central directory record (EOCD)
This however does not account for comments on files and the zip in total. The compression is store (level 0).
This works for the ZIP-implementation i've written. As nickolay-olshevsky pointed out, other compressors might
do things a little different.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With