问题描述:

I have a site where I'm trying to deliver files via WriteFile and they work fine in Chrome and Firefox, but in IE I have to hit "Retry" once or twice to actually make the file download.

Here is the code:

public class DownloadHandler : IHttpHandler

{

public void ProcessRequest(HttpContext context)

{

var r = context.Response;

r.Clear();

r.ClearContent();

r.ContentType = "application/octet-stream";

string path = "";

try

{

if (HttpContext.Current.Request.QueryString["n"] != null)

{

var file = HttpContext.Current.Request.QueryString["n"].ToString();

var type = HttpContext.Current.Request.QueryString["t"].ToString();

r.AddHeader("Content-Disposition", "attachment; filename=" + file.Substring(file.IndexOf('_')+1));

string folder = "";

switch (type.ToLower())

{

case "public":

folder = ConfigurationManager.AppSettings["BCD_PublicDocsLoc"];

break;

case "private":

folder = ConfigurationManager.AppSettings["BCD_PrivateDocsLoc"];

break;

case "internal":

folder = ConfigurationManager.AppSettings["BCD_InternalDocsLoc"];

break;

}

path = folder + "/" + file;

r.WriteFile(path);

r.Flush();

r.Close();

r.End();

}

}

catch (Exception ex)

{

r.Flush();

r.Close();

r.End();

context.Response.Redirect("Error.aspx?err=301");

}

}

public bool IsReusable

{

get

{

return false;

}

}

}

If anyone has any advice as to why this is happening, it would be greatly appreciated. Thanks!

网友答案:

Try substituting the HttpResponse's Close() and End() calls with HttpApplication.CompleteRequest().

Read here why, there are examples too.

Also, this solution was suggested here(in the first answer) for a situation similar to yours.

As was hinted that a small explanation in this post would be convenient, due to the possibility of the links going dead in the future, here it goes:

In short: IE seems to have problems with the HttpResponse.Close and HttpResponse.End methods. Aside of that, anyways, Microsoft recommends in most cases the use of HttpApplication.CompleteRequest over the former two, because:

-HttpResponse.Close() terminates the connection abruptly, dropping buffered data and is not intended for normal HTTP use in which a response to the client is desired

-HttpResponse.End() exists for compatibility reasons with the older ASP technology. It calls the EndRequest event directly and no further code after the End call is executed which is inconvenient in many cases

-HttpApplication.CompleteRequest(): also executes the EndRequest event and it does allow the execution of the code that following the CompleteRequest call, which makes it more appropriate to handle most situations.

网友答案:

Just a hunch but it sounds like an I.E. caching issue to me...

if I.E is set to automatically check for newer pages 'every time i go to the website.' (in [tools\internet options\general\ browsing history\settings]) then you wont have a cache issue. Like I say, only a hunch, but give it a whirl.

If you want to get around this [*1], add a guid to your Query string.[*2]

[*1] The cache setting is a user by user setting, you can never pre-empt the users settings, so work with them instead

[*2] The nocache value is always different, the browser will never have a cached version to go to.

I use something like this...

protected void Page_PreRender(object sender, EventArgs e)
        {
            if (HttpContext.Current.Request.QueryString["FirstRun"] == "1")
            {
                NameValueCollection nvc = HttpUtility.ParseQueryString(Request.Url.Query);
                nvc.Remove("FirstRun");
                string url = Request.Url.AbsolutePath;
                for (int i = 0; i < nvc.Count; i++)
                    url += string.Format("{0}{1}={2}", (i == 0 ? "?" : "&"), nvc.Keys[i], nvc[i]);
                Response.Redirect(string.Format("{1}&NoCache={0}",System.Guid.NewGuid().ToString().Replace("-",""),url));
            }
        }

Any links/redirects to this page need ?FirstRun=1 (or &FirstRun=1) appended to the querystring. The page reload cycles itself once adding a &noCache value to the querystring.

Note: Because you added FirstRun=1, it will always execute twice serverside, but appear like a single load to your user, and the browser.

If you don't add FirstRun=1, it will behave like a normal request as it never gets into the condition.

相关阅读:
Top