XmlHttpRequest Upload Hangs After Pause Between Us

2019-08-10 12:28发布

问题:

I am working on a single page application with a file upload portion. Knockout is used to bind the view to a viewmodel. This application is an intranet application using Windows Authentication and IE10 as the client. If the user initially uploads a file, all is well. If, after 1 upload, there is a 1 minute or more pause and another upload is attempted, the application will hang. Here is my file upload code:

var fileToUpload = document.getElementById(fileInputID).files[0];
var formData = new FormData();
formData.append("file", fileToUpload);
formData.append("queueForUpdate", self.queueForUpdate())

xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.addEventListener("progress", uploadProgressOnChange, false);
xhr.addEventListener("load", uploadOnLoad, false);
xhr.send(formData);

This is what I get back when the failures start:

> HTTP/1.1 401 Unauthorized Content-Type: text/html; charset=us-ascii
> Server: Microsoft-HTTPAPI/2.0 WWW-Authenticate: Negotiate
> oYHkMIHhoAMKAQGhDAYKKwYBBAGCNwICCqKBywSByE5UTE1TU1AAAgAAAAYABgA4AAAAFcKJ4kDoPTPX1ToPEGzyAQAAAACKAIoAPgAAAAYBsR0AAAAPSQBTAEkAAgAGAEkAUwBJAAEAFABEAEIATwBSAE8AUwBTAC0AVwA3AAQAEgBpAHMAaQBkAGMALgBjAG8AbQADACgAZABiAG8AcgBvAHMAcwAtAHcANwAuAGkAcwBpAGQAYwAuAGMAbwBtAAUAEgBpAHMAaQBkAGMALgBjAG8AbQAHAAgAgtoTc21EzwEAAAAA
> Date: Thu, 20 Mar 2014 18:51:48 GMT Content-Length: 341 Proxy-Support:
> Session-Based-Authentication
> 
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML
> 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> <HTML><HEAD><TITLE>Not Authorized</TITLE> <META
> HTTP-EQUIV="Content-Type" Content="text/html;
> charset=us-ascii"></HEAD> <BODY><h2>Not Authorized</h2> <hr><p>HTTP
> Error 401. The requested resource requires user authentication.</p>
> </BODY></HTML>

I have tried adding xhr.withCredentials = true; with no change. I am using the local IIS web server and running the code from Visual Studio 2012.

This is not a cross site request.

回答1:

This issue seems to stem from the way Internet Explorer works with NTLM authentication. IE detects that a site is using NTLM authentication when it receives HTTP 401 responses from the domain. When a large POST operation like the one in my question occur, IE will send a zero byte POST request expecting to get a 401 back which it can then respond to with the user credentials. This prevents the data having to be sent twice.

In my setup I would receive the 401 back and IE seemed to respond to the server with the credentials and the file upload. For whatever reason, the server did not respond to that request which would then timeout.

I found a suggestion in other StackOverflow questions and comments. It was suggested to issue a GET request first and let it authenticate before sending the file upload. This worked for me. Here are the steps my code performs:

  1. Send a HTTP GET request to the server. I created a NOP (no operation) action on my ASP.NET MVC controller for this.
  2. When the server responds to the GET request, perform the file upload call. There doesn't appear to be any challenge/response in this event. The file is sent to the server and the server responds accordingly.

Any comments or explanations would be welcome.