5

I'm generating a file on the fly on the event of a button. I have to following code:

Response.ClearHeaders();
Response.ClearContent();
Response.Buffer = false;
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", "attachment; filename=Duck.xml");
Response.Write("First part");
Response.Flush();

//simulate long operation   
System.Threading.Thread.Sleep(10000);

//Done
Response.Write("Done");
Response.Flush();
Response.End();

I would like the Save As Dialog to appear after the first flush, because the operation can take a while. How would I go about?

After some playing around I discovered that it will buffer 256 characters (reproducible by sending new string('x', 256) to the client).

Kees C. Bakker
  • 32,294
  • 27
  • 115
  • 203
  • Can you try different browsers? It might have to do with the way the TCP client reads data. Also, please try sending more data in the first part (send `new string('x', 1024 * 1024)`). Let's see how these experiments behave. – usr Oct 04 '12 at 11:11
  • Yeah... that works... but now I'm wondering... why ;-) – Kees C. Bakker Oct 04 '12 at 11:17
  • Maybe it has to do with a minimum buffer or something? – Kees C. Bakker Oct 04 '12 at 11:19
  • @usr it seems that I get the SaveAs dialog if I send `new string('x', 256)` characters. – Kees C. Bakker Oct 04 '12 at 11:41
  • I seem to recall that IE have a specific threshold for showing friendly error page, see http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx. I think that might be closely related. – Paciv Oct 05 '12 at 10:59

2 Answers2

2

I'm guessing you're using Internet Explorer because it is clearly stated that it will use a 256 bytes buffer during MIME type detection :

Per the documentation : http://msdn.microsoft.com/en-us/library/ms775147(v=vs.85).aspx

A MIME type is ambiguous if it is "text/plain," "application/octet-stream," an empty string, or null

...

FindMimeFromData typically receives three parameters when invoked—the cache file name (assumed to be derived from the associated URL), a pointer to a buffer containing up to the first 256 bytes of the content, and a "suggested" MIME type that typically corresponds to the server-provided MIME type (through the content-type header).

Then it can't even start to determine MIME type if the first 256 bytes are not sent to fill the buffer. When the MIME type is determined, it correlates to the Windows registry CLSID and decide what kind of UI should be shown for the stream, thus creating the "SaveAs" Dialog.

The most widely used solution seems, as said in the comment, to fill the response with 256 occurence of any character as in : http://encosia.com/easy-incremental-status-updates-for-long-requests/

// Padding to circumvent IE's buffer*
Response.Write(new string('*', 256));  
Response.Flush();

I also remember reading something similar on IE friendly error pages that could be affected by the same kind of behavior, see http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx.

EDIT :

As per @Ben's comment, in your case, with a IE unambiguous content type, setting your to "text/xml" or "application/xml" should solve your problem.

See What Content-Type value should I send for my XML sitemap? for differences.

Community
  • 1
  • 1
Paciv
  • 1,487
  • 10
  • 16
  • I'm actually generating a file, so adding a buffer will corrupt the file right? – Kees C. Bakker Oct 05 '12 at 12:36
  • You're generating xml if I look correctly at your example, any whitespace shouldn't matter in xml, so you can safely add 256 spaces at the file start without altering your file except in size. If adding any character is not acceptable for your requirement, I would suggest going with a file-independant progress bar (showing something like 'generating data'), and send the file in one shot at the end of the progress. – Paciv Oct 05 '12 at 13:17
  • Yeah, that's true, but the idea is that it should not matter what is generated. It seems the real problem is Internet Explorer and not ASP.Net. – Kees C. Bakker Oct 05 '12 at 13:54
  • 1
    If you are generating XML give the correct content-type and IE will not have to guess!!!! – Ben Oct 05 '12 at 13:57
  • @Ben Right, I never even thought of doing that... my bad, that's the right solution, of course. Use `"text/xml"` content type. – Paciv Oct 05 '12 at 14:00
-1

I'm afraid there is no way to do that. The response is sent back only when End() method is called.

AgentFire
  • 8,944
  • 8
  • 43
  • 90
  • 3
    I highly doubt that. Reflector tells me (http://screencast.com/t/bSUuUksgC4E) that it just flushes the file. The CompleteRequest on the ApplicationInstance doesn't do anything related to the response. – Kees C. Bakker Oct 04 '12 at 11:04
  • 2
    Kees has set `HttpResponse.BufferOutput` to `false`, which the [documentation clearly states](http://msdn.microsoft.com/en-us/library/system.web.httpresponse.bufferoutput.aspx) enables the response to return to the client before it's completed on the server. – Richard Szalay Oct 04 '12 at 11:28