How do I set the file size in a Download response?

Asked

Viewed 149 times

6

I have an application where I give an answer by downloading a certain file on the server to the client. I zip the image files that are in a folder on the server and give an answer by manipulating the headers so that the file is downloaded.

I noticed that when this generated file is a little bigger, there is a delay to download it, but it is not displayed in the browser the remaining time to download based on the file size.

An example written in Aspx Webform:

string fullpath = GenerateZippedPhotos(id);

response.ContentType = "application/zip";

response.AddHeader("content-disposition", "filename=remessa_fotos.zip");

response.WriteFile(fullpath);

response.Flush();

To fix the problem described above, what needs to be done?

Is there any way to "talk to the browser" the size of the file being downloaded?

  • I didn’t tag [tag:csharp] because it’s not a language-specific problem

  • 1

    Addheader( "Content-Length", size )

  • That alone will solve?

  • I can’t imagine the need for more than that,

  • @Does Guilhermenascimento really think he needs the C TAG? For me, I just wanted to ask a question in the global context :D

  • If you zip in one stream (without having to write to the hard drive, just in the socket), which is the most standard way to send an arbitrary zip that you don’t want to store on the server, you don’t know the size a priori. I suffer this with Jenkins and Gitlab when I ask to download a zipped directory

  • 1

    @Jeffersonquesado truth, staying in the memory, which anyway was already before recording, although I do not know the behavior of the platform . net (and c#), if the zip is large I don’t know how expensive it could be, maybe a 256k upload and use a flush, even a download limiter, another idea would be a pro zip cache to avoid rework, but if I go into this the suggestions will go far :)

Show 2 more comments

1 answer

10


Basically:

response.AddHeader("Content-Length", "tamanho" );

Remember that the size is in bytes, and only the body of the request, without the headers. Usually the functions that deal with the filesystem get this easily.

In C# (source):

long tamanho = new System.IO.FileInfo("remessa_fotos.zip").Length;

Definition of the W3:

14.13 Content-Length

The Content-Length Entity-header field indicates the size of the Entity-body, in decimal number of Octets, sent to the recipient or, in the case of the HEAD method, the size of the Entity-body that would have been sent had the request been a GET.

   Content-Length    = "Content-Length" ":" 1*DIGIT

An example is

   Content-Length: 3495

Applications SHOULD use this field to indicate the transfer-length of the message-body, unless this is prohibited by the Rules in Section 4.4.

Which, in short, is:

The Content-Length header indicates the octet body size (8-bit units) that will be sent to the recipient, or that would be sent GET in the case of HEAD consultations.

Applications must submit this field unless prohibited by the rules in section 4.4

More in: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

Note: as mentioned by fellow @Jefferson in the comments, there are situations where it is not desirable to determine beforehand the file size. One example is precisely the generation of streams compressed, precisely so you don’t need to store everything in memory or on disk before starting sending. The stream can be generated while already shipped, saving memory and time.

  • Only you need to know a priori the size of the file... If @Wallacemaxters is doing it right (apparently it’s not), it would only send the stream with the generation of ZIP, which can only know the total size of the compression after compress everything, not during compaction

  • 1

    @Jeffersonquesado in this case he would have to send chunked, but then would not be able to answer the question, which is "how to set the size" in order to show the progress bar (no exact size does not, unless he estimated for more and did a padding, which would probably be a bad idea :)

  • I think I can provide an answer later... "in some cases it is not possible/not desirable"...

  • @Jeffersonquesado I think valid, I even thought about talking in the chunked, but if you are willing to post something, I prefer. I think a complement to the issue of streams (mainly dynamically generated, which by the way, I find underused).

  • From the chuncked I don’t dominate, better not to risk than to talk nonsense. But from the "oh-oh" part to zip in memory I will do

  • 1

    @Jeffersonquesado basically this: https://en.wikipedia.org/wiki/Chunked_transfer_encoding - instead of controlling the stream giving the final size, it is sent block by block with only the size of each block already determined, until at the end send an "empty block" to signal the end (and additional headers if relevant).

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.