Pergunta

Estou tentando fazer com que o iOS 6 use POSTs XMLHttpRequest para fazer upload de imagens.Isso funciona em navegadores desktop e Android, mas com o iOS 6 estou recebendo um erro na página que está sendo postada em:"Solicitação de fluxo corporal esgotado" .(Usando o Simulador iOS com o Safari Web Inspector).

Aqui está o código básico da 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.");
}

Ao fazer isso em qualquer outro navegador, o manipulador retorna corretamente e carrega o arquivo.No entanto, com iOS, a página ashx apresenta o erro "solicitação de fluxo de corpo esgotado".

Aqui está uma captura de tela do inspetor:

Request Body Stream Exhausted

Alguma ideia?

ATUALIZAR: Esse problema ocorre apenas quando a autenticação NTLM/Windows está habilitada para o aplicativo no IIS.Com formulários ou autenticação anônima, o upload funciona bem.

Obrigado,

John

Foi útil?

Solução

No iOS 6, o Safari envia o arquivo com a postagem inicial, incluindo o arquivo.Isso significa que o fluxo de arquivos está no final ou "esgotado".

No entanto, com o NTLM, ele receberá um desafio 401 em resposta e terá que reenviar a postagem com as informações de autenticação.Como não redefine o fluxo de arquivos, não é possível enviar o arquivo novamente com a segunda postagem.Você pode ver isso nos logs do IIS.

Pelo que eu sei, não há uma maneira particularmente boa de contornar isso.Estou alterando meu aplicativo móvel para que ele use autenticação de formulário.Direciono o aplicativo móvel para um aplicativo de login separado no mesmo servidor, que está configurado para usar a autenticação do Windows.O aplicativo de login pode então redirecionar de volta para o aplicativo principal com um cookie de autenticação de formulário e tudo estará bem novamente.

Você deve definir a chave da máquina em ambos os aplicativos no arquivo web.config, para que ambos usem as mesmas chaves para criptografia e validação.

O código no aplicativo de login é tão simples quanto

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

Outras dicas

Resolvi o problema não configurando o HTTP Authenticate Head autodefinido no iOS 7 e iOS 8.(A princípio, nosso serviço usa o valor autodefinido para o Authenticate Head).E após o desafio ser tratado pelo delegado, a solicitação terá a opção "Autenticar:NTLMxxx automaticamente" automaticamente.E o Put e o POST funcionam novamente.

Este erro vem no iOS, mas você pode usar uma abordagem diferente, como alterar sua linha de código em formdata, onde você anexando o arquivo

var fd = new FormData();

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

na linha abaixo basicamente não anexe o controle de arquivo, mas use os dados da imagem base64

var reader = new FileReader();

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

reader.onload = function () {

    var base64DataImg = reader.result;            

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

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top