7

Estoy trabajando para que iOS 6 utilice XMLHttpRequest POSTs para cargar imágenes. Esto funciona en los navegadores web de escritorio y Android, pero con iOS 6 recibo un error en la página que se publica en: "Solicitud de flujo de cuerpo agotado". (Usando iOS Simulator con Safari Web Inspector).Carga de imágenes de iOS 6 (iPhone/iPad) "Solicitar flujo de cuerpo agotado" con autenticación NTLM/Windows

Este es el código básico de la página:

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

Al hacer esto en cualquier otro navegador, el controlador devuelve correctamente y carga el archivo. Sin embargo, con iOS, la página de ashx tiene el error "request body stream exhausted".

Aquí es una captura de pantalla del inspector:

Request Body Stream Exhausted

¿Alguna idea?

ACTUALIZACIÓN: Este problema solo se produce cuando la autenticación NTLM/Windows está habilitada para la aplicación en IIS. Con formularios o autenticación anónima, la carga funciona bien.

Gracias,

John

Respuesta

5

En iOS 6, Safari envía el archivo con el mensaje inicial, incluido el archivo. Eso significa que la secuencia de archivos está al final o "agotada".

Sin embargo, con NTLM, obtendrá un desafío 401 en respuesta, y luego tendrá que volver a enviar la publicación con la información de autenticación. Como no restablece la secuencia de archivos, no puede enviar el archivo nuevamente con la segunda publicación. Puedes ver esto en los registros de IIS.

Por lo que sé, no hay una manera particularmente buena de evitarlo. Estoy cambiando mi aplicación móvil, de modo que usa autenticación de formulario. Dirijo la aplicación móvil a una aplicación de inicio de sesión independiente en el mismo servidor, que está configurado para usar la Autenticación de Windows. La aplicación de inicio de sesión puede redireccionar a la aplicación principal con una cookie de autenticación de formulario, y todo vuelve a estar bien.

Debe configurar la clave del equipo en ambas aplicaciones en el archivo web.config, de modo que ambas utilicen las mismas claves para el cifrado y la validación.

El código de la aplicación de inicio de sesión es tan simple como

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

Eso es lo que también he observado.Tu solución es interesante. Por el momento (he enviado un error a Apple para ver si podrían solucionarlo), en realidad tengo la carga del archivo en un iframe no autenticado que carga un archivo en la carpeta temporal de ASP.NET y devuelve un token que la página autenticada utiliza para hacer referencia al recuperar el archivo de la carpeta temporal. –

+0

¿Hay una solución? Tal vez usando WCF, o tal vez usando alguna otra técnica? Estoy en SharePoint, y la autenticación de Windows es un requisito. – harsimranb

0

He resuelto el problema si no se establece el protocolo HTTP autodefinida Autenticación cabeza en iOS 7 y 8. IOS (Al principio, el uso de nuestro servicio valor autodefinido para la cabeza de autenticación). Y después de que el desafío sea manejado por el delegado, la solicitud tendrá automáticamente el encabezado "Autenticar: NTLMxxx automáticamente". Y el Put y el POST funcionan de nuevo.

0

Este error se produce en IOS, pero se puede utilizar enfoque diferente como cambiar su línea de código en FormData donde anexar el archivo

var fd = new FormData(); 

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

a la línea de abajo en el fondo no anexar el control de archivos, sino utilizar el datos de imagen base64

var reader = new FileReader(); 

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

reader.onload = function() { 

    var base64DataImg = reader.result;    

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

}