2012-05-10 11 views
7

Sto usando Ruby per estrarre un URL di un file da scaricare e scaricare. Il nome del file ha caratteri utf8, ad esempio:Come si esegue la codifica URL dei caratteri ASCII?

www.domain.com/.../ÖÇÄÜ360ÓïÒôÖúÀí.txt 

Quando si tenta di scaricare l'URL sopra riportato, non riesce. Utilizzando URI::escape produce un URI che anche non funziona:

www.domain.com/.../%C3%96%C3%87%C3%84%C3%9C360%C3%93%C3%AF%C3%92%C3%B4%C3%96%C3%BA%C3%80%C3%AD.txt 

Ma se io seguo la URL Encoding Reference, funziona:

www.domain.com/.../%D6%C7%C4%DC360%D3%EF%D2%F4%D6%FA%C0%ED.txt 

Ho provato a cercare una funzione in Ruby che fa la stessa identica codifica, ma non sono riuscito a trovarne. Prima di provare a scrivere una funzione che implementa la tabella nel link sopra, voglio chiedere se qualcuno conosce una libreria esistente che lo faccia. E se decido di farlo, quale gamma di caratteri dovrei codificare, ovviamente, non tutto.

sto usando JRuby 1.6.2 con RUBY_VERSION => "1.8.7"

+1

I byte C3 96 sono codificati in formato UTF-8. Lo stesso carattere è rappresentato in ASCII come il singolo byte D6. Quindi un modo per affrontare il problema è convertire i caratteri UTF-8 in ASCII, dove è possibile, e quindi URI :: escape. Ma questo non ti aiuterà per i caratteri Unicode che non hanno equivalenti ASCII. –

+0

Hai provato ['CGI.escape'] (http://ruby-doc.org/stdlib-1.9.3/libdoc/cgi/rdoc/CGI.html#method-c-escape)? –

+0

@DavidGorsline: questo non funziona. Finisco con "?" per tutti i caratteri ad eccezione di "360" e ".txt". L'esempio sopra è un esempio reale, fai se hai qualche idea puoi metterli alla prova sulla stringa "..." 3.60 "..." e "fammi sapere come farlo". Grazie mille per l'aiuto. – Rami

risposta

15

Oh, le gioie di codifiche di caratteri!

Quello che sta succedendo qui è il seguente. Ruby internamente sta memorizzando la stringa che hai estratto come una sequenza di byte che è la codifica utf-8 del nome del file. Quando si chiama URI.escape su di esso, questi byte sono sfuggiti nel formato %xy e la stringa risultante, che ora consiste esclusivamente di byte nell'intervallo ASCII, viene utilizzata come url.

Il server ricevente è però interpretare quei byte (dopo averli unescaping da %xy form) come se fossero in una codifica diversa, in questo caso ISO-8859-1, e quindi il nome del file risultante si tratta con non corrisponde nulla essa ha.

Ecco una dimostrazione utilizzando Ruby 1.9, in quanto ha un migliore supporto per le codifiche.

1.9.3-p194 :003 > f 
=> "ÖÇÄÜ360ÓïÒôÖúÀí.txt" 
1.9.3-p194 :004 > f.encoding 
=> #<Encoding:UTF-8> 
1.9.3-p194 :005 > URI.escape f 
=> "%C3%96%C3%87%C3%84%C3%9C360%C3%93%C3%AF%C3%92%C3%B4%C3%96%C3%BA%C3%80%C3%AD.txt" 
1.9.3-p194 :006 > g = f.encode 'iso-8859-1' 
=> "\xD6\xC7\xC4\xDC360\xD3\xEF\xD2\xF4\xD6\xFA\xC0\xED.txt" 
1.9.3-p194 :007 > g.encoding 
=> #<Encoding:ISO-8859-1> 
1.9.3-p194 :008 > URI.escape g 
=> "%D6%C7%C4%DC360%D3%EF%D2%F4%D6%FA%C0%ED.txt" 

La soluzione in questo caso è quindi per codificare la stringa come ISO-8859-1 prima scampo. In Ruby 1.9 si esegue questa operazione come sopra, nelle versioni precedenti è possibile utilizzare Iconv (sto assumendo JRuby comprende Iconv, io non sono in realtà che la familiarità con JRuby):

1.8.7 :001 > f 
=> "\303\226\303\207\303\204\303\234360\303\223\303\257\303\222\303\264\303\226\303\272\303\200\303\255.txt" 
1.8.7 :005 > g = Iconv.conv('iso-8859-1', 'utf-8', f) 
=> "\326\307\304\334360\323\357\322\364\326\372\300\355.txt" 
1.8.7 :006 > URI.escape f 
=> "%C3%96%C3%87%C3%84%C3%9C360%C3%93%C3%AF%C3%92%C3%B4%C3%96%C3%BA%C3%80%C3%AD.txt" 
1.8.7 :007 > URI.escape g 
=> "%D6%C7%C4%DC360%D3%EF%D2%F4%D6%FA%C0%ED.txt" 

Si noti che, in generale, si puo' t dipende dal server che usa una particolare codifica. È dovrebbe essere usando utf-8, ma ovviamente non è in questo caso.

+0

Fantastico, grazie! – Rami

+0

Questo è stato molto utile non avevo idea che avevo bisogno di URI.escape dopo la codifica. – KnuturO

Problemi correlati