Envio de grandes conjuntos de dados com AJAX

April 4, 2006

Hoje, totalmente por acaso, descobri alguns macetes para envio e recepção de grandes quantidades de dados usando requisições HTTP assíncronas, como por exemplo textos. Estou trabalhando em um sistema que permite que o usuário cadastre pareceres sobre informações do sistema, e estes pareceres não tem limitação de tamanho.O sistema foi implementado com AJAX, para permitir que os pareceres sejam carregados dinâmicamente, e gravados assincronamente.

O primeiro problema que tive foi que os textos enviados eram sempre truncados em 4096 bytes. A primeira reação foi verificar se estava enviando os dados via POST ou GET: o correto é enviar por POST, uma vez que GET tem tamanho limitado. Os dados realmente estavam sendo enviados por POST, que a priori não tem limitação alguma. Pesquisando um pouco, descobri que precisava definir um header Content-length com o tamanho do conteúdo do texto, antes de enviar a requisição. O comando correto é

requestObject.open('POST', url, true);
requestObject.setRequestHeader('Content-Type',
                             'application/x-www-form-urlencoded');
if (parameters != null)
    requestObject.setRequestHeader("Content-length",
                                   parameters.length);
requestObject.send(parameters);
Bom, eu não sou um expert do protocolo HTTP, mas a minha explicação seria que de fato o método POST aceita uma quantidade ilimitada de dados, mas por default ele define o tamanho máximo como 4096, para evitar erros. Caso o usuário deseje enviar mais, deve informar o tamanho total.

Resolvido este problema, tive um problema semelhante ao ler os dados para exibir na tela. Meu sistema abre uma requisição AJAX, que envia um XML contendo o texto do parecer inserido pelo usuário. Para recuperar o texto, executava o seguinte comando:

var value = decodeURIComponent(
                 root.getElementsByTagName('value')[0].
                                       firstChild.data);
Este código retornava o texto corretamente no IE, mas cortava em 4096 bytes (novamente !) no Firefox. O mais estranho é que tanto no envio quanto na recepção, o XML gerado estava correto. Portanto o problema estava na leitura do CDATA do XML. Fuçando um pouco (desta vez não encontrei nada na internet), descobri que em caso de CDATA com mais de 4096 bytes, o DOM do Firefox considera que a tag value possui mais de um nó filho, cada um com no máximo 4K. Assim, o código correto para obter o texto em ambos os navegadores é
for(var i=0; i i++)
     value += decodeURIComponent(
                     root.getElementsByTagName('value')[0]
                           .childNodes[i].data);

tags: , ,
posted in Desenvolvimento by Miguel Galves

Follow comments via the RSS Feed | Leave a comment | Trackback URL

  • Fernando Rego

    Bicho, estou há três dias às voltas com um problema em js/xls/ajax. Eu tenho o XML retornando e sendo lido perfeitamente, mas eu não sei previamente quais os tagNames que virão. E não consigo passar variável nanhuma, pois sempre me retorna “objeto requerido”.

    No seu exemplo, seria como se eu não soubesse que o nome da tag fosse ‘value’. Eu preciso muito descobrir qual é o nome da tag, além do seu childNode.

    Já passou por isso?

  • http://log4dev.com/ Miguel Galves

    Fernando,

    se eu entendi bem, voce quer saber o nome da tag antes de processar, pq as tags podem vir com nomes aleatórios, certo ?

    bom, pra obter o nome da tag, é so usar node.nodeName, onde node é o nó do arquivo que te interessa.

    Espero que isso ajude.

  • Fernando Rego

    Opa! Miguel, é quase isso! Realmente dei uma passo à frente com a sua dica. Mas ainda tenho como resposta “Objeto necessário”. Vou postar parte do código (com comentários), se puder verificar, agradeço novamente. Obrigado.

    • Parte do XML que seria resposta: 40 Agente 1 br Brasil
    • EOF
    • javascript: function processXML(obj) { var arr = obj.getElementsByTagName("agent");
  • http://rec6.via6.com/link2.php?url=http%3A%2F%2Flog4dev.com%2F2006%2F04%2F04%2Fenvio-de-grandes-conjuntos-de-dados-com-ajax%2F via Rec6

    Envio de grandes conjuntos de dados com AJAX

    “Hoje, totalmente por acaso, descobri alguns macetes para envio e recep

  • http://www.ajaxbox.com.br Otavio Nogueira

    Opa, recomendo você a ler o codigo em javascript do framework ajaxbox ;) tem bastante coisa sobre ajax para se estudar..

    boa sorte.

  • http://www.aiatola.net Micael

    caramba

    obrigado pelo aviso cara nosso sistema ta todo baseado em ajax e com esse problema no firefox, pois a questão do header já estava resolvida.

    existe alguma outra solução?

    estamos a procura aqui

  • Wanderlei Hüttel

    Utilizei o “Content-length” no cabeçalho, porém não obtive sucesso. Será que alguem poderia me dar uma ajuda?

    Obrigado Wanderlei

  • http://log4dev.com/ Miguel Galves

    Wanderlei, se puder me passar mais informações por email (miguel em log4dev.com), talvez eu consiga te ajudar. []s

  • Ronald

    olá…no meu tbm nao deu certo…coloquei o Content-length mas nao envia para o browser… pode me ajudar ?

  • Miguel Galves

    É só me escrever em miguel em log4dev.com e mandar mais informações. Na medida do possível, eu ajudo.

  • http://www.ogicomunicacao.com.br Rodrigo Cesar

    Cara fantástico… já sofri pakara com esse problema do Content… nem acredito que tah resolvido!!!

    Vi que a galera não está conseguindo então vai aki a dica……. vou mandar a funcao completa pra vcs:

    function ajax(url) {

    req = null; // Procura por um objeto nativo (Mozilla/Safari) if (window.XMLHttpRequest) { req = new XMLHttpRequest(); req.onreadystatechange = processReqChange; req.open(“POST”,url,true); //Aqui você estipula o header req.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’);

    //EH AQUI QUE ENTRA A DEFINIÇÃO DO Content-Type if (url != null){ req.setRequestHeader(“Content-length”, url.length); }else{ url = null } req.send(url);

    //req.send(null);

    // Procura por uma versão ActiveX (IE) } else if (window.ActiveXObject) { req = new ActiveXObject(“Microsoft.XMLHTTP”); if (req) {

    req.onreadystatechange = processReqChange; req.open(“POST”,url,true); //Mesmo esqueminha….. if (url != null){ req.setRequestHeader(“Content-length”, url.length); }else{ url = null } req.send(url);

    //req.send(); } } }

    Vou aproveitar pra postar aki se tem uma maneira de pegar por ajax uma url externa……

    Eu consegui burlar pelo IE…. mas no FF naum dá…… Dá “Access Denied”

    Vlw galera!

  • edkardoso

    NÃO FUNCIONOU! Mesmo colocando o cabeçalho indicado, ele continua limitando o envio do meu texto. Alguém tem aí outra sugestão ???

  • diego

    cara nem sei como te agradecer! eu nunca teria descoberto isso não fosse esse post. valeu! abraço

blog comments powered by Disqus

Switch to our mobile site

 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org