iOS 6(iPhone / iPad)使用NTLM / Windows身份validation将图像上传为“请求正文stream”

我正在尝试让iOS 6使用XMLHttpRequest POSTs来上传图片。 这适用于桌面和Android Web浏览器,但在iOS 6中,我在发布到“Request Body Stream Exhausted”的页面上出现错误。 (通过Safari Web Inspector使用iOS模拟器)。

这里是页面的基本代码:

function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; if (file) { var fileSize = 0; if (file.size > 1024 * 1024) fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB'; else fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB'; document.getElementById('fileName').innerHTML = 'Name: ' + file.name; document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize; document.getElementById('fileType').innerHTML = 'Type: ' + file.type; } } function uploadFile() { var fd = new FormData(); fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]); var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress, false); xhr.addEventListener("load", uploadComplete, false); xhr.addEventListener("error", uploadFailed, false); xhr.addEventListener("abort", uploadCanceled, false); xhr.open("POST", "/UploadHandler.ashx"); xhr.send(fd); } function uploadProgress(evt) { if (evt.lengthComputable) { var percentComplete = Math.round(evt.loaded * 100 / evt.total); document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%'; document.getElementById('prog').value = percentComplete; } else { document.getElementById('progressNumber').innerHTML = 'unable to compute'; } } function uploadComplete(evt) { /* This event is raised when the server send back a response */ alert(evt.target.responseText); } function uploadFailed(evt) { alert("There was an error attempting to upload the file."); } function uploadCanceled(evt) { alert("The upload has been canceled by the user or the browser dropped the connection."); } 

在其他浏览器上执行此操作时,处理程序将正确返回并上载该文件。 但是,在iOS中,ashx页面有错误“请求主体stream已耗尽”。

这是检查员的截图:

请求身体流用尽

有任何想法吗?

更新:只有在IIS中为应用程序启用NTLM / Windows身份validation时,才会出现此问题。 通过表单或匿名身份validation,上传工作正常。

谢谢,

约翰

在iOS 6中,Safari会发送包含文件的初始文章。 这意味着文件stream是在最后,或“枯竭”。

但是,对于NTLM来说,它会得到一个401的挑战,然后必须重新发送authentication信息。 由于它不会重置文件stream,所以无法在第二篇文章中重新发送文件。 你可以在IIS日志中看到这个。

据我所知,没有特别好的方法。 我正在更改我的移动应用程序,以便它使用表单身份validation。 我将移动应用程序指向设置为使用Windows身份validation的同一服务器上的单独login应用程序。 login应用程序然后可以redirect到主应用程序与表单身份validationcookie,一切都很好。

您必须在web.config文件中的两个应用程序上设置机器密钥,以便两者都使用相同的密钥进行encryption和validation。

login应用程序的代码就像

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.Load With HttpContext.Current.User.Identity If .IsAuthenticated Then Dim sUser As String = .Name.ToLower.Trim FormsAuthentication.RedirectFromLoginPage(s, False) End If End With End Sub 

我通过在iOS 7和iOS 8上不设置自定义的HTTP Authenticate Head来解决这个问题(首先,我们的服务使用Authentate Head的自定义值)。 在委托处理完挑战之后,请求将自动具有“Authenticate:NTLMxxx自动”标题。 Put和POST再次工作。

这个错误来自IOS,但你可以使用不同的方法,如在附加文件的formdata中更改代码行

 var fd = new FormData(); fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]); 

对下面的行基本不附加文件控件而是使用base64图像数据

 var reader = new FileReader(); reader.readAsDataURL(opmlFile.files[0]); reader.onload = function () { var base64DataImg = reader.result; base64DataImg = base64DataImg.replace('data:'imagetype';base64,', ''); }