2012-05-10 2 views
7

Я использую Ruby для извлечения URL-файла файла для его загрузки и загрузки. Имя файла имеет символы utf8, например:Как кодировать URL-символы ASCII?

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

При попытке загрузить указанный выше URL-адрес он терпит неудачу. Использование URI::escape производит URI, который также не работает:

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 

Но если следовать URL Encoding Reference, он работает:

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

Я пытался искать функции в Ruby, который делает точно такой же кодирования, но я не мог найти. Прежде чем попытаться написать функцию, которая реализует таблицу в приведенной выше ссылке, я хочу спросить, знает ли кто-нибудь какую-либо существующую библиотеку, которая делает это. И если я решил сделать это, то какой диапазон символов я должен кодировать, очевидно, не все.

Я использую JRuby 1.6.2 с RUBY_VERSION => "1.8.7"

+1

Байты C3 96 являются кодированными UTF-8 .... Тот же символ представлен в ASCII как одиночный байт D6. Таким образом, одним из способов решения этой проблемы является преобразование ваших символов UTF-8 в ASCII, где вы можете, а затем URI :: escape. Но это не поможет вам для символов Unicode, которые не имеют эквивалента ASCII. –

+0

Вы пробовали ['CGI.escape'] (http://ruby-doc.org/stdlib-1.9.3/libdoc/cgi/rdoc/CGI.html#method-c-escape)? –

+0

@DavidGorsline: Это не работает. Я в конечном итоге с?? для всех символов, кроме «360» и «.txt». Пример, приведенный выше, является реальным примером, если у вас есть какие-либо идеи, вы можете проверить их на строке «................» и сообщить мне, как это сделать. Большое спасибо за помощь. – Rami

ответ

15

О, радости кодировками!

Что здесь происходит, так это следующее. Ruby внутренне хранит строку, которую вы извлекли, в виде последовательности байтов, которая является кодировкой utf-8 имени файла. Когда вы вызываете на нем URI.escape, эти байты экранируются в формате %xy, и в качестве URL-адреса используется результирующая строка, которая теперь состоит только из байтов в диапазоне ASCII.

Принимающий сервер, однако, интерпретирует эти байты (после неэкранированных их %xy формы), как если бы они были в другой кодировке, в этом случае ISO-8859-1, и поэтому результирующее имя файла он придумывает не соответствует ничего его есть.

Вот демонстрация с использованием Ruby 1.9, так как она имеет лучшую поддержку кодировок.

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" 

Раствор в этом случае поэтому кодировать строку как ISO-8859-1 до выхода его. В Ruby 1.9 вы сделаете это, как указано выше, в более ранних версиях вы можете использовать Iconv (я предполагаю, что JRuby включает Iconv, на самом деле я не знаком с 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" 

Обратите внимание, что в целом вы можете» t зависит от сервера, используя какую-либо конкретную кодировку. Это должно быть использовать utf-8, но, очевидно, это не так.

+0

Удивительный, спасибо! – Rami

+0

Это было очень полезно, не имел понятия, что мне нужно для URI.escape после кодирования. – KnuturO

Смежные вопросы