7

Pracuję nad tym, aby uzyskać iOS 6, aby używać postów XMLHttpRequest do przesyłania obrazów. Działa to w przeglądarkach na komputerach i urządzeniach z Androidem, ale w systemie iOS 6 pojawia się błąd na stronie, która jest wysyłana do: "Żądanie wygaszenia strumienia ciała". (Korzystanie z symulatora systemu iOS za pomocą Safari Web Inspector).iOS 6 (iPhone/iPad) Przesyłanie obrazu "Żądany strumień ciała wyczerpany" z uwierzytelnianiem NTLM/Windows

Oto podstawowy kod strony:

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

Kiedy robi to w każdej innej przeglądarce, opiekun zwraca poprawnie i przesyła plik. Jednak w przypadku iOS strona ashx zawiera błąd "zażądano strumienia treści żądania".

Oto zrzut ekranu inspektora:

Request Body Stream Exhausted

Jakieś pomysły?

AKTUALIZACJA: Ten problem występuje tylko wtedy, gdy jest włączone uwierzytelnianie NTLM/Windows dla aplikacji w IIS. W przypadku formularzy lub uwierzytelniania anonimowego przesyłanie działa poprawnie.

Dzięki,

John

Odpowiedz

5

W iOS 6, Safari wysyła plik z początkowego postu, w tym pliku. Oznacza to, że strumień plików znajduje się na końcu lub "wyczerpany".

Jednak w przypadku NTLM otrzyma odpowiedź 401, a następnie będzie musiał ponownie wysłać wiadomość z informacjami uwierzytelniającymi. Ponieważ nie resetuje strumienia plików, nie może ponownie wysłać pliku z drugim wpisem. Możesz to zobaczyć w dziennikach IIS.

O ile mi wiadomo, nie ma na to szczególnie dobrej metody. Zmieniam moją aplikację mobilną, aby używała uwierzytelniania formularza. Kieruję aplikację mobilną do oddzielnej aplikacji logowania na tym samym serwerze, na którym ustawiono korzystanie z uwierzytelniania systemu Windows. Aplikacja do logowania może następnie przekierować z powrotem do głównej aplikacji za pomocą pliku cookie uwierzytelniania formularza, a wszystko znowu jest dobrze.

Musisz ustawić klucz komputera w obu aplikacjach w pliku web.config, aby oba używały tych samych kluczy do szyfrowania i sprawdzania poprawności.

Kod na aplikacji logowania jest tak proste jak

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

To jest rzeczywiście to, co zaobserwowałem.Twoje rozwiązanie jest interesujące. Na razie (przesłałem do Apple błąd, aby sprawdzić, czy może to naprawić), faktycznie mam plik do przesłania w niezarejestrowanym elemencie iframe, który przesyła plik do folderu tymczasowego ASP.NET i przekazuje token że strona uwierzytelniona następnie używa do odniesienia podczas pobierania pliku z folderu tymczasowego. –

+0

Czy istnieje obejście? Może przy użyciu WCF, a może przy użyciu innej techniki? Jestem na SharePoint i wymagana jest autoryzacja Windows. – harsimranb

0

I rozwiązać problem, nie ustawiając samodzielne zdefiniowane HTTP Uwierzytelnij głowę na iOS 7 i iOS 8. (Na początku korzystania z naszych usług własna wartość dla Głowy Uwierzytelniającej). Po podjęciu wyzwania przez delegata żądanie automatycznie otrzyma nagłówek "Uwierzytelnij: NTLMxxx automatycznie". A Put i POST znów działają.

0

Ten błąd Komes na IOS, ale można użyć innego podejścia jak zmienić linię kodu w formdata gdzie dołączając plik

var fd = new FormData(); 

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

do linii poniżej zasadzie nie dołączy kontrolę pliku, ale użyć 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,', '');  

}