2015-11-29 1 views
0

J'expérimente avec CGI et le codage chunked (champ d'en-tête HTTP "Transfer-Encoding: chunked"). De cette façon, les fichiers peuvent être envoyés sans en-tête de longueur de contenu. J'ai écrit une application CGI minimaliste dans Ruby, pour l'essayer. Mon code est le suivant (chunked.rb):cURL: encodage malformé trouvé dans l'encodage en bloc, pourquoi?

#!/usr/bin/ruby 

puts "Date: Fri, 28 Nov 2015 09:59:59 GMT" 
puts "Content-Type: application/octet-stream; charset=\"ASCII-8BIT\"" 
puts "Content-Disposition: attachment; filename=image.jpg" 
puts "Transfer-Encoding: chunked" 
puts 

File.open("image.jpg","rb"){|f| 
while data=f.read(32) 
    STDOUT.puts data.size.to_s(16) 
    STDOUT.puts data 
end 
STDOUT.puts "0" 
STDOUT.puts 
} 

Je pris l'idée et l'exemple de format CHUNKED d'ici: https://www.jmarshall.com/easy/http/

HTTP/1.1 200 OK 
Date: Fri, 31 Dec 1999 23:59:59 GMT 
Content-Type: text/plain 
Transfer-Encoding: chunked 

1a; ignore-stuff-here 
abcdefghijklmnopqrstuvwxyz 
10 
1234567890abcdef 
0 
some-footer: some-value 
another-footer: another-value 
[blank line here] 

Comme mon application CGI réside dans Apache répertoire cgi-bin, je peut émettre cURL:

curl http://example.com/cgi-bin/chunked.rb -O -J 

cURL doit reassamble le fichier image.jpg d'origine des morceaux, mais malheureusement, le fichier enregistré est pas terminé, il est plus petit que l'original, et je reçois un Erro message r aussi de cURL:

curl: (56) Malformed encoding found in chunked-encoding 

Cependant quand je change de ligne data=f.read(32) à quelque chose comme data=f.read(1024*50), puis le fichier est enregistré correctement. L'utilisation d'un autre fichier plus gros du serveur rend l'application CGI inutilisable, j'ai encore reçu le même message d'erreur. Que puis-je faire pour que mon application CGI fonctionne et pour envoyer le fichier correctement?

+1

Après la longueur et les données, le séparateur doit être un 'CRLF' (\ r \ n). 'puts' ajoute juste un' LF' (\ n), ce qui peut être le problème. Est-ce que cela fonctionne si vous mettez '\ r \ n' après chaque longueur et chaque segment de données? – drew010

+0

En fait, il devrait fonctionner "\ r \ n" et "\ n" aussi. Mais problème résolu, c'est un "gotcha" Ruby. Au lieu de "STDOUT.puts data" J'ai dû utiliser "STDOUT.print data" suivi d'un "puts". C'est parce que lorsque les données se terminent accidentellement avec un "\ n", ruby ​​n'ajoute pas de "\ n" supplémentaire. Et parfois cela arrive, quand la taille du morceau interfère avec "\ n" octets dans le fichier binaire. – Konstantin

+0

Content que vous soyez sur la bonne voie - bon travail pour que ça marche. – drew010

Répondre

2

Ainsi, l'exemple de travail:

puts "Date: Fri, 28 Nov 2015 09:59:59 GMT" 
    puts "Content-Type: application/octet-stream; charset=\"ASCII-8BIT\"" 
    puts "Content-Disposition: attachment; filename=image.jpg" 
    puts "Transfer-Encoding: chunked" 
    puts 

    File.open("image.jpg","rb"){|f| 
    while data=f.read(32) 
     STDOUT.puts data.size.to_s(16) 
     STDOUT.print data 
     STDOUT.puts 
    end 
    STDOUT.puts "0" 
    STDOUT.puts 
    }