Net::HTTP get

Ciao a tutti,
avrei bosigno di porvi un quesito.

Ho creato un programmino con Qt-ruby che fa la copia in locale di alcuni
file presenti su un server remoto.

La richiesta HTTP la faccio così:

resp=Net::HTTP.get(URI.parse(‘http://’ + url + ‘:’ + port + path))

dove url, port e path sono variabili settate in precedenza.

Una volta effettuati tutti i controlli sulla presenza o meno della
cartella di destinazione, eseguo la scrittura del file.

fileExport = File.new(dir + “/CVIn” + @countDir.to_s + “/” +
nameFile,“wb”)
fileExport.write(resp)
fileExport.close

Però succede che mentre sta cercando di eseguire la get mi dà questo
genere di errore:

c:/ruby/lib/ruby/1.8/net/protocol.rb:84:in <<': failed to allocate memory (NoMe moryError) from c:/ruby/lib/ruby/1.8/net/protocol.rb:84:inread’
from c:/ruby/lib/ruby/1.8/net/http.rb:2209:in read_body_0' from c:/ruby/lib/ruby/1.8/net/http.rb:2170:inread_body’
from c:/ruby/lib/ruby/1.8/net/http.rb:2195:in body' from c:/ruby/lib/ruby/1.8/net/http.rb:2134:inreading_body’
from c:/ruby/lib/ruby/1.8/net/http.rb:1049:in request' from c:/ruby/lib/ruby/1.8/net/http.rb:945:inrequest_get’
from c:/ruby/lib/ruby/1.8/net/http.rb:380:in get_response' ... 8 levels... from c:/ruby/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:241:inqt_metacall’
from c:/ruby/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:241:in
method_missing ' from c:/ruby/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:241:inexec’
from Export_main.rb:35

Io credo che l’errore sia legato al fatto che cerca di portare tutto in
RAM.

Qualcuno sa dirmi di più?
Qualcuno sa indicarmi un’alternativa?
Spero che la mia richiesta non resti inascoltata…

Grazie mille a tutti, anticipatamente

Catiana

Catiana T. wrote:

Ciao a tutti,
avrei bosigno di porvi un quesito.

Ho creato un programmino con Qt-ruby che fa la copia in locale di alcuni
file presenti su un server remoto.

La richiesta HTTP la faccio così:

resp=Net::HTTP.get(URI.parse(‘http://’ + url + ‘:’ + port + path))

dove url, port e path sono variabili settate in precedenza.

Una volta effettuati tutti i controlli sulla presenza o meno della
cartella di destinazione, eseguo la scrittura del file.

fileExport = File.new(dir + “/CVIn” + @countDir.to_s + “/” +
nameFile,“wb”)
fileExport.write(resp)
fileExport.close

Però succede che mentre sta cercando di eseguire la get mi dà questo
genere di errore:

c:/ruby/lib/ruby/1.8/net/protocol.rb:84:in <<': failed to allocate memory (NoMe moryError) from c:/ruby/lib/ruby/1.8/net/protocol.rb:84:in read’
from c:/ruby/lib/ruby/1.8/net/http.rb:2209:in read_body_0' from c:/ruby/lib/ruby/1.8/net/http.rb:2170:in read_body’
from c:/ruby/lib/ruby/1.8/net/http.rb:2195:in body' from c:/ruby/lib/ruby/1.8/net/http.rb:2134:in reading_body’
from c:/ruby/lib/ruby/1.8/net/http.rb:1049:in request' from c:/ruby/lib/ruby/1.8/net/http.rb:945:in request_get’
from c:/ruby/lib/ruby/1.8/net/http.rb:380:in get_response' ... 8 levels... from c:/ruby/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:241:in qt_metacall’
from c:/ruby/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:241:in
method_missing ' from c:/ruby/lib/ruby/site_ruby/1.8/Qt/qtruby4.rb:241:in exec’
from Export_main.rb:35

Io credo che l’errore sia legato al fatto che cerca di portare tutto in
RAM.

Qualcuno sa dirmi di più?
Qualcuno sa indicarmi un’alternativa?
Spero che la mia richiesta non resti inascoltata…

Grazie mille a tutti, anticipatamente

Catiana

Potresti anche fare un socket che legge piano piano il contenuto. Ad
esempio:

path = “/”#Il percorso del documento sul server
nomefile = “result.txt” #Il nome del file in locale
server = “www.x.com#Il nome del server (senza http:// nè il resto del
percorso)
port = 80 #La porta del server

File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\n” #Esegue una richiesta di tipo GET.
while select([sock],[],[],1.5)[0][0] == sock #Verifica che il socket sia
pronto e che il file non sia finito
export = File.open(nomefile, “a+”) {|file| #Riapre il file in modalitÃ
Append
file.write sock.recv(1024) #Scrive 1KB appena letto dal socket
} #Chiude il file
end

Prova se funziona, in teoria non dovrebbe dare più errori come
NoMemoryError (prendendo solo 1KB alla volta). Poi in base alla
grandezza della ram e del file, puoi modificare il “1024” in recv.

Catiana T. wrote:

Potresti anche fare un socket che legge piano piano il contenuto. Ad
esempio:

path = “/”#Il percorso del documento sul server
nomefile = “result.txt” #Il nome del file in locale
server = “www.x.com#Il nome del server (senza http:// nè il resto del
percorso)
port = 80 #La porta del server

File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\n” #Esegue una richiesta di tipo GET.
while select([sock],[],[],1.5)[0][0] == sock #Verifica che il socket sia
pronto e che il file non sia finito
export = File.open(nomefile, “a+”) {|file| #Riapre il file in modalitÃ
Append
file.write sock.recv(1024) #Scrive 1KB appena letto dal socket
} #Chiude il file
end

Prova se funziona, in teoria non dovrebbe dare più errori come
NoMemoryError (prendendo solo 1KB alla volta). Poi in base alla
grandezza della ram e del file, puoi modificare il “1024” in recv.

Ciao Simone,
prima di tutto grazie per aver risposto.

Mi dà però un’altro genere di errore:

undefined method `[]’ for nil:NilClass

credo che il punto in cui si fermi sia questo:
while select([sock],[],[],1.5)[0][0] == sock

Grazie tante.
Catiana

Vero, hai ragione. Infatti select ritorna “nil” se non va a buon fine.
Quindi bisogna farlo separatamente:

risultato = true
while risultato
… (tutto quello di prima)
risultato = select([sock],[],[],1.5)
risultato = (risultato[0][0] == sock) if risultato != nil
end

Prova ora, spero che non dia altri errori.

Potresti anche fare un socket che legge piano piano il contenuto. Ad
esempio:

path = “/”#Il percorso del documento sul server
nomefile = “result.txt” #Il nome del file in locale
server = “www.x.com#Il nome del server (senza http:// nè il resto del
percorso)
port = 80 #La porta del server

File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\n” #Esegue una richiesta di tipo GET.
while select([sock],[],[],1.5)[0][0] == sock #Verifica che il socket sia
pronto e che il file non sia finito
export = File.open(nomefile, “a+”) {|file| #Riapre il file in modalitÃ
Append
file.write sock.recv(1024) #Scrive 1KB appena letto dal socket
} #Chiude il file
end

Prova se funziona, in teoria non dovrebbe dare più errori come
NoMemoryError (prendendo solo 1KB alla volta). Poi in base alla
grandezza della ram e del file, puoi modificare il “1024” in recv.

Ciao Simone,
prima di tutto grazie per aver risposto.

Mi dà però un’altro genere di errore:

undefined method `[]’ for nil:NilClass

credo che il punto in cui si fermi sia questo:
while select([sock],[],[],1.5)[0][0] == sock

Grazie tante.
Catiana

Vero, hai ragione. Infatti select ritorna “nil” se non va a buon fine.
Quindi bisogna farlo separatamente:

risultato = true
while risultato
… (tutto quello di prima)
risultato = select([sock],[],[],1.5)
risultato = (risultato[0][0] == sock) if risultato != nil
end

Prova ora, spero che non dia altri errori.

Ciao Simone,
credo ci sia ancora qualcosa che non va.
Mi spiego:

il codice, correggimi se sbaglio dovrebbe essere così:

path = @pathChildrennomefile = @em_mw.cmbDirectory.currentText + “/CVIn”
+
@countDir.to_s + “/” +
nameFile
server = “10.0.0.1”
port = 9200
File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
risultato = true
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\n” #Esegue una richiesta di tipo GET
while risultato
export = File.open(nomefile, “a+”) {|file|
file.write(sock.recv(1024))
} #Chiude il file
risultato = select([sock],[],[],1.5)
risultato = (risultato[0][0] == sock) if risultato != nil
end

Ora se provo a stampare a video sock.puts "GET #{path} HTTP/1.1\r\n
ciò che ho è nil; infatti il programmino sembra bloccarsi ma non genera
errori.

Grazie mille per la tua disponibilità , davvero.

Catiana

Ciao Simone,
credo ci sia ancora qualcosa che non va.
Mi spiego:

il codice, correggimi se sbaglio dovrebbe essere così:

path = @pathChildrennomefile = @em_mw.cmbDirectory.currentText + “/CVIn”
+
@countDir.to_s + “/” +
nameFile
server = “10.0.0.1”
port = 9200
File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
risultato = true
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\n” #Esegue una richiesta di tipo GET
while risultato
export = File.open(nomefile, “a+”) {|file|
file.write(sock.recv(1024))
} #Chiude il file
risultato = select([sock],[],[],1.5)
risultato = (risultato[0][0] == sock) if risultato != nil
end

Ora se provo a stampare a video sock.puts "GET #{path} HTTP/1.1\r\n
ciò che ho è nil; infatti il programmino sembra bloccarsi ma non genera
errori.

Grazie mille per la tua disponibilità , davvero.

Catiana

Sì, effettivamente ora che lo provo vedo che non funziona. Era sbagliata
la richesta GET. Ecco la versione testata. Ancora ci dovrò lavorare un
po’, perché (provando con un file exe) non fa proprio un lavoro
eccellente, però se si tratta di scaricare qualcosa di meno “preciso”,
va bene.

path = “/”#Il percorso del documento sul server
nomefile = “result.txt” #Il nome del file in locale
server = “www.google.it” #Il nome del server (senza http:// nè il resto
del percorso)
port = 80 #La porta del server

File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\nHost: #{server}\r\n\r\n” #Esegue una
richiesta di tipo GET.
sock.recv(1024) #Riceve gli header non necessari
times = 0 #Serve a eliminare dal file la grandezza in byte dei dati che
il server invia
loop do
written = “”
export = File.open(nomefile, “a+”) {|file| #Riapre il file in modalitÃ
Append
written=sock.recv(1024) #Scrive 1KB appena letto dal socket (senza
scrivere gli header)
if times == 0
spltn = written.split("\r\n")
file.write spltn[1,spltn.size-1].join("\r\n")
else
file.write written
end
} #Chiude il file
if written.delete("\r\n") == “” or written.delete("\r\n") == “0”
break
end
times += 1
end

path = “/”#Il percorso del documento sul server
nomefile = “result.txt” #Il nome del file in locale
server = “www.google.it” #Il nome del server (senza http:// nè il resto
del percorso)
port = 80 #La porta del server

File.open(nomefile,“wb”) {|f|} #Crea il file vuoto
sock = TCPSocket.new(server,port) #Si collega al server
sock.puts “GET #{path} HTTP/1.1\r\nHost: #{server}\r\n\r\n” #Esegue una
richiesta di tipo GET.
sock.recv(1024) #Riceve gli header non necessari
times = 0 #Serve a eliminare dal file la grandezza in byte dei dati che
il server invia
loop do
written = “”
export = File.open(nomefile, “a+”) {|file| #Riapre il file in modalitÃ
Append
written=sock.recv(1024) #Scrive 1KB appena letto dal socket (senza
scrivere gli header)
if times == 0
spltn = written.split("\r\n")
file.write spltn[1,spltn.size-1].join("\r\n")
else
file.write written
end
} #Chiude il file
if written.delete("\r\n") == “” or written.delete("\r\n") == “0”
break
end
times += 1
end

Grazie mille Simone, ora funziona.
Non so davvero come ringraziarti!!
Sei stato gentilissimo.

Grazie ancora.

Catiana