0

I'm struggling achieving a solution to download multiple files at once on my web site.

I've tried a client approach but it didn't work because the files I want to open are images and it doesn't work with images (iframe solution).

I've looked to Google's Picasa or Google+ and it would be perfect to have their multidownload solution: they build their zip "on-demand" which means the browser keeps downloading a file, not knowing its final size, but once it achieved 100%, it stops and everything worked smoothly.

I don't do any idea of how to do this. Any ideas?

Tks!

  • By "client approach", do you mean you were trying to generate a zip file using JS in the browser? – Asad Saeeduddin Mar 20 '14 at 02:02
  • Please provide more info, where is the code you have tried, are there any links that would make understanding the question easier, or make it clearer ? – fuzzybear Mar 20 '14 at 02:04
  • You can use [`ZipFile`](http://msdn.microsoft.com/en-us/library/system.io.compression.zipfile%28v=vs.110%29.aspx) and compile one using the content, then dump it out as a content stream. BTW, ASP.NET classic or MVC? – Brad Christie Mar 20 '14 at 02:04

1 Answers1

3

Based on Alexei Levenkov and OP's comments, I've learned that it is possible to begin writing a zip file to a stream without having to completely assemble it before hand. Fortunately, .NET 4.5 provides a built in utility class for exactly this purpose: System.IO.Compression.ZipArchive.

Unfortunately, as described in this question, this class has a few incompatibilities with the HttpResponse.OutputStream which we intend to write to, since HttpResponse.OutputStream is not seekable, whereas ZipArchive requires any stream it writes to implement the Position member for a seekable stream.

There is hope however: svick has posted an answer that diagnoses the issue and provides a way to work around it. The workaround involves simply creating a "go-between" stream, which implements the members ZipArchive requires, and simply forwards whatever is written to it into another stream (i.e. Response.OutputStream).


If you want to create the zip file server side, which I think is easier, you might want to look at the System.IO.Compression.ZipFile class, which provides static methods for creating archives from existing files.

Eg. creating an archive from a directory on the server:

// In ASP.NET, getting the UNC path to the directory which will be zipped
string dirpath = Server.MapPath('~/app/foldertodownload');

// Destination path
string destpath = Server.MapPath('~/public/downloads.zip');

ZipFile.CreateFromDirectory(dirpath, destpath);

Now all you need to do is write this zip file to the response with the appropriate headers.

Community
  • 1
  • 1
Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
  • I think it doesn't suits me because my files are on Amazon S3. I want something like: - Amazon S3 Link 1 (4mb) https://s3.amazon.com/file1.jpg - Amazon S3 Link 2 (2mb) https://s3.amazon.com/file2.jpg - Amazon S3 Link 3 (5mb) https://s3.amazon.com/file3.jpg Start downloading the files and sending them to user, ocupping the less resources possible (RAM is the main issue, disk space is no issue) – Carlos Monteiro Mar 20 '14 at 02:09
  • I don't understand what you mean by `I want something like: - Amazon S3 Link 1 (4mb)`. Do you want to know how to hyperlink to these downloads? – Asad Saeeduddin Mar 20 '14 at 02:11
  • Nops! Imagine you're on a image gallery and start choosing pictures. At the end of your selection, you click download and a zip starts downloading IMMEDIATELY with the selected files. What I saw on some websites that do this, they do "straming" the zip to the user: the browser doesn't know the final size but keeps downloading 'til it ends. – Carlos Monteiro Mar 20 '14 at 02:15
  • Downloading "immediately" is impossible, the server must at the very least locate the files to be zipped and assemble them into the archive format. It may seem immediate to *you* because they have good servers and can do this very quickly, but they aren't really doing anything different from what I've posted above. Create the zip archive from the files you want to select, then write it to the response stream just as you would any other file download. The user will see a download begin once the response stream is flushed. – Asad Saeeduddin Mar 20 '14 at 02:19
  • @Asad Check out Zip format (i.e. [Wiki](http://en.wikipedia.org/wiki/ZIP_%28file_format%29) ) - it contains directory *at the end* so it is possible to stream files as needed and add directory when done. Now is there trivial implementation in .Net already I don't know, but checking overrides based on `Stream` not files may be good option. – Alexei Levenkov Mar 20 '14 at 02:31
  • @AlexeiLevenkov Indeed, now that I've a bit more homework based on the links you've provided, there is a built in .NET way to stream zip archives without having to write them completely to a buffer first. I'll add this to my answer. – Asad Saeeduddin Mar 20 '14 at 02:36
  • Thank you guys but I have a huge restriction: only .net 2.0. Any workaround? – Carlos Monteiro Mar 20 '14 at 10:45