7

Ich arbeite an dem Versuch, iOS 6 XMLHttpRequest POSTs zum Hochladen von Bildern zu verwenden. Dies funktioniert auf Desktop- und Android-Webbrowsern, aber mit iOS 6 erhalte ich einen Fehler auf der Seite, auf der gepostet wird: "Body Stream Exhausted anfordern". (Verwenden von iOS Simulator mit dem Safari Web Inspector).iOS 6 (iPhone/iPad) Bild Hochladen "Request Body Stream Exhausted" mit NTLM/Windows Authentifizierung

Hier ist die grundlegende Code der Seite:

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."); 
} 

Wenn diese auf einen anderen Browser zu tun, der Handler kehrt richtig und lädt die Datei. Bei iOS hat die Aschx-Seite jedoch den Fehler "Körperstrom abfragen".

Hier ist ein Screenshot des Inspektors:

Request Body Stream Exhausted

Irgendwelche Ideen?

UPDATE: Dieses Problem tritt nur auf, wenn die NTLM/Windows-Authentifizierung für die Anwendung in IIS aktiviert ist. Mit Formularen oder anonymer Authentifizierung funktioniert der Upload einwandfrei.

Danke,

John

Antwort

5

In iOS 6 sendet Safari die Datei mit dem ersten Beitrag, der Datei enthält. Das bedeutet, dass der Dateistream am Ende oder "erschöpft" ist.

Bei NTLM wird jedoch eine 401-Abfrage als Antwort angezeigt, und der Beitrag muss erneut mit den Authentifizierungsinformationen gesendet werden. Da der Dateistream nicht zurückgesetzt wird, kann die Datei mit dem zweiten Post nicht erneut gesendet werden. Sie können dies in den IIS-Protokollen sehen.

Soweit ich weiß, gibt es keinen besonders guten Weg. Ich ändere meine mobile App, sodass sie die Formularauthentifizierung verwendet. Ich leite die mobile App auf eine separate Login-App auf demselben Server, auf dem die Windows-Authentifizierung aktiviert ist. Die Login-App kann dann mit einem Formularauthentifizierungs-Cookie zurück zur Haupt-App weitergeleitet werden, und alles ist wieder gut.

Sie müssen den Computerschlüssel für beide Apps in der Datei web.config festlegen, damit beide die gleichen Schlüssel für die Verschlüsselung und Validierung verwenden.

Der Code auf der Login-Anwendung ist so einfach wie

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 
+2

Das ist tatsächlich was ich auch beobachtet habe.Ihre Lösung ist interessant. Vorläufig (ich habe einen Fehler an Apple gesendet, um zu sehen, ob sie es beheben können), habe ich die Datei tatsächlich in einem nicht authentifizierten iframe hochladen, der eine Datei in den temporären ASP.NET-Ordner hochlädt und ein Token zurückgibt dass die authentifizierte Seite dann verwendet, um beim Abrufen der Datei aus dem Temp-Ordner zu verweisen. –

+0

Gibt es eine Problemumgehung? Vielleicht mit WCF oder vielleicht mit einer anderen Technik? Ich bin in SharePoint und Windows-Authentifizierung ist eine Voraussetzung. – harsimranb

0

ich das Problem, indem nicht die Einstellung des selbstdefinierten HTTP Authentifizieren Kopf auf iOS 7 und iOS 8. gelöst (Zuerst unser Service nutzt die selbstdefinierter Wert für den Authenticate Head). Und nachdem die Anfrage vom Delegaten bearbeitet wurde, wird die Anfrage automatisch den Header "Authenticate: NTLMxxx automatisch" erhalten. Und das Put und POST funktioniert wieder.

0

Dieser Fehler kommt auf IOS aber Sie anderen Ansatz verwenden können wie Ihre Codezeile in Formulardaten ändern, in dem Sie die

var fd = new FormData(); 

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

auf die unterhalb der Linie grundsätzlich Datei anhängen anhängen nicht die Steuerdatei, sondern verwenden die base64 image data

var reader = new FileReader(); 

reader.readAsDataURL(opmlFile.files[0]); 

reader.onload = function() { 

    var base64DataImg = reader.result;    

    base64DataImg = base64DataImg.replace('data:'imagetype';base64,', '');  

}