Forum: Rails France envoi de données à partir de JavaScript: err eur "EOFError

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
38790c4b7ff8235ae989405b534e0288?d=identicon&s=25 Michael Hulet (Guest)
on 2007-02-21 13:52
(Received via mailing list)
Salut tout l'monde,

J'ai un problème que je ne parviens pas à résoudre. Je vous explique...

Pour le projet en cours, une extension Firefox a été développée. Son job
c'est de récupérer les images trouvées sur une page et de les envoyer
sur le serveur. Pour ce faire, le développeur utilise un objet
XMLHttpRequest et il poste les données sous forme de
multipart/form-data. Voici le code JavaScript pour l'envoi d'une des
images:

    const BOUNDARY = "111222111"; //ce qui va nous servir de délimiteur

    const MULTI    = "@mozilla.org/io/multiplex-input-stream;1";
    const FINPUT   = "@mozilla.org/network/file-input-stream;1";
    const STRINGIS = "@mozilla.org/io/string-input-stream;1";
    const BUFFERED = "@mozilla.org/network/buffered-input-stream;1";

    const nsIMultiplexInputStream =
    Components.interfaces.nsIMultiplexInputStream;
    const nsIFileInputStream      =
    Components.interfaces.nsIFileInputStream;
    const nsIStringInputStream    =
    Components.interfaces.nsIStringInputStream;
    const nsIBufferedInputStream  =
    Components.interfaces.nsIBufferedInputStream;

    var mis =
    Components.classes[MULTI].createInstance(nsIMultiplexInputStream);

    var fin =
    Components.classes[FINPUT].createInstance(nsIFileInputStream);
    fin.init(fileTmp, 0x01, 0444, 4);

    var sheader = new String();

    sheader += "\r\n" + "--" + BOUNDARY + "\r\n";
    sheader += "Content-disposition:
    form-data;name=\"page_url\"\r\n\r\n"+encodeURIComponent(pageUrl);

    sheader += "\r\n" + "--" + BOUNDARY + "\r\n";
    sheader += "Content-disposition:
    form-data;name=\"img_url\"\r\n\r\n"+encodeURIComponent(imagesListArray[indiceArray[i]][5]);

    sheader += "\r\n" + "--" + BOUNDARY + "\r\n";

    sheader += "Content-disposition:
    form-data;name=\"commentaires\"\r\n\r\n"+encodeURIComponent(commentArray[i]);

    sheader += "\r\n" + "--" + BOUNDARY + "\r\n";

    sheader += "Content-disposition:
    form-data;name=\"page_title\"\r\n\r\n"+encodeURIComponent(pageTitle);
    sheader += "\r\n" + "--" + BOUNDARY + "\r\n";

    sheader += "Content-disposition:
    form-data;name=\"filename\";filename=\"" + fileTmp.leafName +
"\"\r\n";
    sheader += "Content-Type: application/octet-stream\r\n";
    sheader += "Content-Length: " + fileTmp.fileSize+"\r\n\r\n";

    var hsis =
    Components.classes[STRINGIS].createInstance(nsIStringInputStream);
    hsis.setData(sheader, sheader.length);

    var endsis =
    Components.classes[STRINGIS].createInstance(nsIStringInputStream);
    var bs = new String("\r\n--" + BOUNDARY + "--\r\n");
    endsis.setData(bs, bs.length);
    var buf =
    Components.classes[BUFFERED].createInstance(nsIBufferedInputStream);
    buf.init(fin, 4096);

    mis.appendStream(hsis);
    mis.appendStream(buf);
    mis.appendStream(endsis);

    var xmlr = new XMLHttpRequest();
    xmlr.open("POST", urlServeur, true);
    xmlr.setRequestHeader("Content-Type", "multipart/form-data;
    boundary=" + BOUNDARY);
    xmlr.onreadystatechange=function() { /* ici du code vérifiant le
    statut pour voir si c'est bien passé */ }
    xmlr.send(mis);

Pour ses tests, le développeur a écrit un script PHP qui récupère les
données envoyées et renvoie un code erreur. Ca fonctionne parfaitement.
Mais je souhaite l'intégrer complètement au projet et donc j'ai réécrit
son code en Ruby. J'appelle la méthode et là, l'extension me sort une
erreur 404 (xmlr.status = 404), comme quoi elle ne parvient pas à
joindre le serveur.

J'ai un peu fouiné dans les logs et j'ai trouvé ceci dans mongrel.log:

    Wed Feb 21 13:30:15 +0100 2007: Error calling Dispatcher.dispatch
    #<EOFError: bad content body>
    /usr/lib/ruby/1.8/cgi.rb:983:in `read_multipart'
    /home/web/projet.com/ftp/dev/config/../vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb:38:in
    `initialize_query'
    /usr/lib/ruby/1.8/cgi.rb:2274:in `initialize'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/cgi.rb:50:in
    `initialize'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/rails.rb:76:in
    `new'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/rails.rb:76:in
    `process'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:580:in
    `process_client'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:579:in
    `each'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:579:in
    `process_client'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:686:in
`run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:686:in
    `initialize'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:686:in
`new'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:686:in
`run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:673:in
    `initialize'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:673:in
`new'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:673:in
`run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/configurator.rb:267:in
    `run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/configurator.rb:266:in
    `each'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/configurator.rb:266:in
    `run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/bin/mongrel_rails:127:in
    `run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel/command.rb:211:in
    `run'
    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/bin/mongrel_rails:231

L'erreur qui m'emphe de traiter les données est donc: #<EOFError: bad
content body>. J'ai fouiné sur Google, pas moyen de trouver pourquoi ça
passe mal. J'ai modifié le code JavaScript pour qu'il n'envoie plus
l'image et n'envoie rien que des données basiques (l'url de la page,
l'url de l'image, etc), mais ça n'a rien changé. Bref, je suis un peu
coincé...

Avez-vous une idée? Que pourrais-je faire pour résoudre ce problème?

Bonne après-midi à tous,

Michael
23363756763c69bd790a71582c24230a?d=identicon&s=25 loiseau gaetan (Guest)
on 2007-02-21 14:18
(Received via mailing list)
Michael Hulet a écrit :
>
>    const nsIStringInputStream    =
>    var sheader = new String();
>        sheader += "Content-disposition:
> "\"\r\n";
>    var buf =
>    xmlr.onreadystatechange=function() { /* ici du code vérifiant le
>
>
>    `process_client'
>    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/lib/mongrel.rb:673:in
>    `each'
>    /usr/lib/ruby/gems/1.8/gems/mongrel-0.3.13.4/bin/mongrel_rails:231
> Bonne après-midi à tous,
>
> Michael
>
>
> _______________________________________________
> Railsfrance mailing list
> Railsfrance@rubyonrails.fr
> http://lists.rubyonrails.fr/mailman/listinfo/railsfrance
>
Salut,
    Tu pourait nous joindre le dump exacte de ce que XMLHttpRequest
envoie ?

merci
38790c4b7ff8235ae989405b534e0288?d=identicon&s=25 Michael Hulet (Guest)
on 2007-02-21 15:10
loiseau gaetan wrote:
> Salut,
>     Tu pourait nous joindre le dump exacte de ce que XMLHttpRequest
> envoie ?

J'imagine qu'il s'agit de ceci (exactement entouré par les ++++
ci-dessous):

++++


--111222111

Content-disposition: form-data;name="page_url"



http%3A%2F%2Fdmoz.org%2F

--111222111

Content-disposition: form-data;name="img_url"



undefined

--111222111

Content-disposition: form-data;name="commentaires"





--111222111

Content-disposition: form-data;name="page_title"



ODP%20-%20Open%20Directory%20Project

--111222111

Content-disposition:
form-data;name="filename";filename="1172066678008_0"

Content-Type: application/octet-stream

Content-Length: 1095




++++
Cae31409db980bf8f32e4172ef026c50?d=identicon&s=25 Vincenzo Ruggiero (vincenzo)
on 2007-02-21 22:33
Je ne suis pas certain qu'il soit possible de passer de donner
multipart/form-data via AJAX ??

Je me trompe peut-être.
38790c4b7ff8235ae989405b534e0288?d=identicon&s=25 Michael Hulet (Guest)
on 2007-02-22 10:26
Vincenzo Ruggiero wrote:
> Je ne suis pas certain qu'il soit possible de passer de donner
> multipart/form-data via AJAX ??

Le script PHP récupère parfaitement les données, donc c'est possible,
non?
Cae31409db980bf8f32e4172ef026c50?d=identicon&s=25 Vincenzo Ruggiero (vincenzo)
on 2007-02-22 10:35
Michael Hulet wrote:
> Vincenzo Ruggiero wrote:
>> Je ne suis pas certain qu'il soit possible de passer de donner
>> multipart/form-data via AJAX ??
>
> Le script PHP récupère parfaitement les données, donc c'est possible,
> non?

J'utilisais des form_remote_tag avec des input type="file", il m'était
impossible de récupérer les data en utilisant le form_remote_tag.

En passant en form_tag pas de problème.

Je me trompe peut-être, à voir.
9713dd2ed86923b44c78108a2a83f012?d=identicon&s=25 Renaud Morvan (Guest)
on 2007-02-22 11:43
(Received via mailing list)
Le 22 févr. 07 à 10:35, Vincenzo Ruggiero a écrit :

>
> En passant en form_tag pas de problème.
>
> Je me trompe peut-être, à voir.

Sans avoir investigué des heures j'avais abouti à la même conclusion
que Vincenzo à savoir pas d'upload possible via XHR.

Le workaround pour faire du remote upload c'est la sousmission d'un
formulaire dans une iframe ce qui dans les fait à le même effet mais
est particulièrement pénible dans rails car pas vraiment compatible
avec response_to et RJS.

Renaud_______________________________________________
Railsfrance mailing list
Railsfrance@rubyonrails.fr
http://lists.rubyonrails.fr/mailman/listinfo/railsfrance
7c1cf44366644d1928a05ebe29519dee?d=identicon&s=25 Yann Strass (strass)
on 2007-02-22 11:50
(Received via mailing list)
Renaud Morvan a écrit :
> Le workaround pour faire du remote upload c'est la sousmission d'un
> formulaire dans une iframe ce qui dans les fait à le même effet mais
> est particulièrement pénible dans rails car pas vraiment compatible
> avec response_to et RJS.
Plus précisément, ce n'est pas vraiment compatible avec RJS et
Prototype/Scriptaculous. J'utilise de plus en plus jQuery parce qu'avec
Prototype/Scriptaculous je bute un peu trop souvent sur ce genre de
problèmes. Et justement, il existe un plugin pour jQuery (ajaxUpload)
avec lequel l'upload via la soumission d'un formulaire via une iframe
fonctionne très bien et de manière plutôt propre.

++

yk
38790c4b7ff8235ae989405b534e0288?d=identicon&s=25 Michael Hulet (Guest)
on 2007-02-22 12:53
Mon problème est réglé. Tout d'abord, j'ai du modifié le code
JavaScript:

  var sheader = new String();


//  sheader += "\r\n" + "--" + BOUNDARY + "\r\n"; // ANCIENNE LIGNE

  sheader += "--" + BOUNDARY + "\r\n"; // NOUVELLE LIGNE

  sheader += "Content-disposition:
form-data;name=\"page_url\"\r\n\r\n"+encodeURIComponent(pageUrl);


J'ai donc enlevé le "\r\n" du début.

Ensuite ça n'allait toujours pas, parce que dans cgi.rb, il y a un test
que voici:

  /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)

J'ai donc modifié les lignes incriminées:

//  sheader += "Content-disposition:
form-data;name=\"page_url\"\r\n\r\n"+encodeURIComponent(pageUrl);
  sheader += "Content-disposition:form-data;
name=\"page_url\"\r\n\r\n"+encodeURIComponent(pageUrl);

C'était subtil (une histoire de whitespaces mal placés)... Maintenant
les données sont bien récupérées par le contrôleur.
Ee01e594333a9e631173d0d8e4350214?d=identicon&s=25 didier lafforgue (Guest)
on 2007-02-22 17:16
(Received via mailing list)
Ola everybody,

Bon, je vais peut-etre rendre la vie plus facile a certains. J'ai dans
mes
cartons un petit plugin qui fait fonctionner le rendu rjs sur l'upload
de
fichier par iFrame. C'est un plugin qui derive de responds_to_parent: (
http://sean.treadway.info/svn/plugins/responds_to_parent/)  (Note: j'ai
maille son auteur mais il ne m'a jamais repondu).

Attention, je ne garantis rien, il marche chez moi car j'ai des besoins
assez simple. Mais bon vous avez les sources donc, a vous de jouer !

----------------

Utilisation:

1/ Vue:

<%= form_tag_with_fake_ajax_upload({ :action => 'save', :id => @my_model
},
{ :target => 'uploadIframe', :begin => "alert('Hello world !'" }) %>
   ...
   <%= file_field 'foo', 'file' %>
   ...
   <%= submit_tag "Save" -%>

<%= end_form_tag %>

Remarque: :target (qui est le nom d'une iFrame) n'est pas obligatoire.
En
fait, cela l'est dans le cas ou l'utilisateur utilise Safari ET que
l'application essaye par exemple d'effacer le form pour le remplacer par
une
nouvelle version.


2/  Controlleur:


def save
  ....

  # 2 possibilites (c'est une ou l'autre pas les deux en meme temps :-)
 render_rjs_after_upload :update do |page|
   page.alert 'Youpi ca marche !'
 end

 # Ou
 # render_rjs_after_upload :action => 'save'
 # execute save.rjs pour le rendu
end

-----------------

Ou le trouver ? http://www.lafforgue.fr/fake_ajax_upload.tar.gz

Il y aurait pas mal de choses a ameliorer mais ce plugin remplira sa
tache
parfaitement dans 90% des cas. J'oubliais, les tests unitaires ne
marchent
pas, desole.


   Did

Le 22/02/07, Yann Klis <strass@strasslab.net> a écrit :
This topic is locked and can not be replied to.