Проблема с upload'ом файлов с русскими именами
Прислано: Ustas
чт, 05/04/2007 - 14:42
Platform: Gentoo Linux (locale: UTF-8) + Apache2 + PHP5 + MySQL
Drupal version: 5.1
Столкнулся с такой проблемой. При добавлении файлов с русскоязычными именами в названии файла отрезается первое слово до первого пробела или символа подчеркивания. В результате IE не может открывать прикрепленные к нодам файлы. В FF все работает.
С англоязычными именами файлов все ок.
На Drupal.org ничего не нашел по этому поводу. Сталкивался ли кто-нибудь с подобной проблемой?
- Ustas's blog
- Для комментирования войдите или зарегистрируйтесь
попробкуйте транслитерировать файлы,при сохранении на сервер.
А вообще национальные алфавиты в коммандной строке броузера(без преобразования),а хотят и доменные имена-бред полнейший(imho).
Попробуй найти и отличить mama,мaмa и mамa :)
======================================================
Документация,Дизайн,Переводы
- Для комментирования войдите или зарегистрируйтесь
я тоже думал над этой проблемой.
надо бы как то патч написать, чтобы имена файлов в транслите хранились, только ума не хватает и времени разобраться с этим.
- Для комментирования войдите или зарегистрируйтесь
1 php функция :)======================================================
Документация,Дизайн,Переводы
- Для комментирования войдите или зарегистрируйтесь
у меня ощущение, что транслитерация должна производиться еще на стороне клиента (если загрузка производится с помощью AJAX'овского интерфейса). Если же транслитерацию делать на стороне сервера, то тогда подскажите, какую функцию использовать - я в стандартной библиотеке PHP такого не помню (только в PECL что-то было, по-моему)..
А вообще, процесс решения проблемы я бы разбил на следующие шаги:
- Определить, где происходит потеря первого слова (на стороне клиента или уже на сервере) - для этого надо проанализировать, что приходит из формы на сервер.
- В зависимости от того, где происходит потеря слова, добавить преобразование в транслит там, где косяк возникает.
Кто поможет?
- Для комментирования войдите или зарегистрируйтесь
Это модуль upload?
Я ставлю строчку "php_value error_reporting 7" в файл .htaccess, а вы? :)
Полный русский перевод Drupal 5.x и еще некоторых модулей.
- Для комментирования войдите или зарегистрируйтесь
Да, видимо, он.
- Для комментирования войдите или зарегистрируйтесь
Ничего предосудительного в национальных алфавитах в URLе не вижу (с доменными именами, действительно, перебор). Патчить модуль надо на предмет urlencode() и urldecode(), чтоб это работало везде. Ну и разобраться кто первое слово отрезает.
Что-то не нашёл на drupal.org issue по этому поводу. Действительно нет, или плохо искал? Проблема-то, похоже, давняя.
- Для комментирования войдите или зарегистрируйтесь
а русские буквы и на диске в некоторых файловых системах плохо сохраняются
поэтому надо взять функцию транслита из pathauto и вставить в upload или еще лучше дописать ее в ядро потому что iconv не всегда правильно работает и не у всех есть
- Для комментирования войдите или зарегистрируйтесь
уважаемый kiev1
не могли бы назвать имя функции транслита из pathauto?
- Для комментирования войдите или зарегистрируйтесь
function pathauto_cleanstring($string) {
- Для комментирования войдите или зарегистрируйтесь
значит надо использовать нормальные файловые системы, где проблем с алфавитами нет
а транслитерировать всё - это идиотизм
представьте себе бизнес-портал, на котором собираются люди, не разбирающиеся в компьютерах
и дела им нет ни до каких файловых систем и кодировок
а тут имена файлов (например, msword - сплошь и рядом) преобразуются в транслит
неудобно и неимиджево
ps: поглядел upload.module.. там все строковые ф-ии восьмибитные.. не ожидал, что такое будет в ядре, тем более для некоторых есть врапперы (drupal_strlen, drupal_strtolower и drupal_strtoupper)
- Для комментирования войдите или зарегистрируйтесь
что будем делать? ;)
- Для комментирования войдите или зарегистрируйтесь
я запостил репорт на drupal.org, пока тишина..
боюсь, придётся самостоятельно патч писать - им-то что, им юникод не нужен
- Для комментирования войдите или зарегистрируйтесь
плохи дела
слово отрезает php функция basename, которая криво работает с unicode
см. file.inc ф-ию file_check_upload
- Для комментирования войдите или зарегистрируйтесь
хм, продолжаем изыскания
basename нормально отрабатывает и ничего не отрезает в случае, если запускать с локалью ru_RU.UTF-8
короче, quick & dirty hack прилагаю
- Для комментирования войдите или зарегистрируйтесь
Спасибо. Потестирую сегодня и сообщу о результатах. :)
- Для комментирования войдите или зарегистрируйтесь
Походу, не помогло. Кэш браузера и в базе почистил - нифига. :(
- Для комментирования войдите или зарегистрируйтесь
Локаль на сервере была выставлена в POSIX. Поправил на ru_RU.UTF-8 в соответствие с этим мануалом: http://ru.gentoo-wiki.com/HOWTO_ru_RU.utf8_Gentoo_way
$ locale LANG=ru_RU.UTF-8 LC_CTYPE="ru_RU.UTF-8" LC_NUMERIC="ru_RU.UTF-8" LC_TIME="ru_RU.UTF-8" LC_COLLATE="ru_RU.UTF-8" LC_MONETARY="ru_RU.UTF-8" LC_MESSAGES="ru_RU.UTF-8" LC_PAPER="ru_RU.UTF-8" LC_NAME="ru_RU.UTF-8" LC_ADDRESS="ru_RU.UTF-8" LC_TELEPHONE="ru_RU.UTF-8" LC_MEASUREMENT="ru_RU.UTF-8" LC_IDENTIFICATION="ru_RU.UTF-8" LC_ALL=
Проблема осталась. :( какие еще могут быть варианты?
- Для комментирования войдите или зарегистрируйтесь
общесистемную локаль нет смысла выставлять, если патч не помог - то и от этого мало толку
в системе, вообще, присутствует локаль ru_RU.UTF-8? команда date чего показывает?
возможно, надо пересобрать php - не знаю точно, где он локали берёт.. или просто положить их ему
попробуй ещё print_r вставить в file.inc в эту ф-ию после basename - может это не он обрезает, хотя вряд ли..
- Для комментирования войдите или зарегистрируйтесь
Локаль присутствует:
$ locale -a | grep ru ru_RU ru_RU.koi8r ru_RU.utf8 ru_UA ru_UA.utf8 $ $ date Mon Apr 23 14:25:23 MSD 2007
Как посмотреть локаль, используемую php? в phpinfo нашел только:
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Content-Type: text/html; charset=cp-1251
Не в этом ли проблема кроется?
- Для комментирования войдите или зарегистрируйтесь
в phpinfo есть ещё вот что
LANG => ru_RU.UTF-8
_SERVER["LANG"] => ru_RU.UTF-8
_ENV["LANG"] => ru_RU.UTF-8
- Для комментирования войдите или зарегистрируйтесь
пример, демонстрирующий, что я хочу сказать:
user@host:~$ cat test.php
#!/usr/bin/php5
<?php
$var = "раз два три\n";
setlocale(LC_CTYPE, 'C');
print basename($var);
setlocale(LC_CTYPE, 'ru_RU.UTF-8');
print basename($var);
user@host:~$ ./test.php
два три
раз два три
user@host:~$?>- Для комментирования войдите или зарегистрируйтесь
хм-м-м... у меня нет LANG в переменных окружения.. и приведенный пример выдает:
два три два три
- Для комментирования войдите или зарегистрируйтесь
Похоже это баг php: http://bugs.php.net/bug.php?id=37945
Обновляю до 5.2.1-r3
- Для комментирования войдите или зарегистрируйтесь
обновление помогло?
- Для комментирования войдите или зарегистрируйтесь
Пока не знаю. Завтра посмотрю - там много зависимостией тянулось, поэтой я в screen'е запустил. О результате сообщу. :)
- Для комментирования войдите или зарегистрируйтесь
хмм.. странно
у меня 5.2.0
user@host:~$ dpkg -l | grep php
ii libapache2-mod-php5 5.2.0-8+etch1 server-side, HTML-embedded scripting language
ii php5 5.2.0-8+etch1 server-side, HTML-embedded scripting language
ii php5-cli 5.2.0-8+etch1 command-line interpreter for the php5 script
ii php5-common 5.2.0-8+etch1 Common files for packages built from the php
ii php5-gd 5.2.0-8+etch1 GD module for php5
ii php5-mcrypt 5.2.0-8+etch1 MCrypt module for php5
ii php5-mysql 5.2.0-8+etch1 MySQL module for php5
- Для комментирования войдите или зарегистрируйтесь
Проблема решилась обновлением. Теперь все ок!
Всем огромное спасибо! :)
- Для комментирования войдите или зарегистрируйтесь
уважаемый USTAS не могли бы вы дать описание своих действий а также конфигурации php и OS в которой у вас функционирует сохранение файлов с символами кирилицы???
P.S. большое спасибо.
- Для комментирования войдите или зарегистрируйтесь
Сервер работает под управлением Gentoo Linux.
$ uname -a
Linux bodhidharma 2.6.14-gentoo-r2 #1 SMP PREEMPT Wed Nov 23 10:23:02 Local time zone must be set-- i686 Intel(R) Xeon(TM) CPU 3.06GHz GenuineIntel GNU/LinuxЛокаль: ru_RU.UTF-8 (настроена по этому мануалу: http://ru.gentoo-wiki.com/HOWTO_ru_RU.utf8_Gentoo_way - он подходит только для Gentoo)
Apache 2.0.58-r2
$ php -v PHP 5.2.1-pl3-gentoo (cli) (built: May 2 2007 14:28:54) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
Все собирал из стандартных портежей Gentoo. USE-Флаги:
net-www/apache mpm-prefork -ldap threads dev-lang/php -* cli apache2 ctype expat fastbuild ftp gd hash iconv memlimit mysql nls pcre pic pdo reflection session simplexml sockets spl ssl tokenizer truetype unicode xml xsl zlib
- Для комментирования войдите или зарегистрируйтесь
все равно надо как-то в друпале сделать транслитезацию при аплоаде файлов, потому что очень большая вероятность их потери при неудачном переносе или бекапе (некоторые фтп клиенты, или архиваторы).
- Для комментирования войдите или зарегистрируйтесь
У меня тоже самое. Как решить эту проблему? ASAP
Версии:
Apache 1.3.37 (Unix)
PHP 5.2.3
Проблема и на этом сервере существует:
имя файла было:
а тут как_эта проблема работает.txt
стало:
тут как_эта проблема работает.txt
- Для комментирования войдите или зарегистрируйтесь
ну да, там где локаль utf-8 оно работает вроде нормально, но если юзер начнет копировать кривыми ftp клиентами - то они могут подменить имя файла - а в базе он останется под другим именем - и тогда он не будет находиться.
- Для комментирования войдите или зарегистрируйтесь
Так что же тогда делать?
Надо как то решать. так жить нельзя на друпале.
В drupal 6.0beta2 проблема остается...
- Для комментирования войдите или зарегистрируйтесь
так и нету нормального решения проблемы?
- Для комментирования войдите или зарегистрируйтесь
Кто успел попробовать http://drupal.org/project/transliteration ?
- Для комментирования войдите или зарегистрируйтесь
после установки модуля http://drupal.org/project/transliteration все заработало как надо
- Для комментирования войдите или зарегистрируйтесь
По поводу модуля transliteration - добавил обработку прикрепленных файлов в комментариях и некоторую косметику (это для пятой версии, авторам тоже отправил); но если локаль неправильно работает - я не уверен в результате, т.к. тут тоже используется функция basename.
/** * Helper function; retroactive transliteration of existing filenames. */ function transliteration_install_retroactive() { require_once(drupal_get_path('module', 'transliteration') .'/transliteration.inc'); // Regexp operators differ between database manufacturers. switch ($GLOBALS['db_type']) { case 'mysql': case 'mysqli': $op = 'RLIKE'; break; case 'pgsql': $op = '~*'; break; } // Get all of the files that need to be converted, that is those that // contain characters other than alphanumerics, underscores, dots, or // hyphens. // aka: added routines for 'filename' field $result = db_query("SELECT fid, filename, filepath FROM {files} WHERE SUBSTRING_INDEX(filepath, '/', -1) $op '[^0-9A-Za-z_.-]'"); $errors = array(); while ($file = db_fetch_object($result)) { // Transliterate the file's name. $filepath = $file->filepath; // aka: new code $filename_new = transliteration_clean_filename(basename($filepath)); $filepath_new = dirname($filepath) .'/'. $filename_new; // aka: old version //$filepath_new = dirname($filepath) .'/'. transliteration_clean_filename(basename($filepath)); // Move the file to a new location but do a shortcut check first to avoid // unneccessary error messages. It's probably better to not mess with // records for missing files. $realpath = realpath($filepath); if ($realpath && file_exists($realpath) && file_move($filepath, $filepath_new, FILE_EXISTS_RENAME)) { // Get the file's new path; it may have changed. $filepath_new = $filepath; // Update the files table with the new path. db_query("UPDATE {files} SET filename = '%s', filepath = '%s' WHERE fid = %d", $filename_new, $filepath_new, $file->fid); } else { $errors[] = 'table files: ' . $file->filepath; } } // aka: repeat routines for comment_upload_files $result = db_query("SELECT fid, filename, filepath, description FROM {comment_upload_files} WHERE SUBSTRING_INDEX(filepath, '/', -1) $op '[^0-9A-Za-z_.-]'"); $errors = array(); while ($file = db_fetch_object($result)) { // Transliterate the file's name. $filepath = $file->filepath; // aka: new code $filename_new = transliteration_clean_filename(basename($filepath)); $filepath_new = dirname($filepath) .'/'. $filename_new; // aka: translate description $description_new = ($file->filename == $file->description) ? $filename_new : $file->description; // aka: old version //$filepath_new = dirname($filepath) .'/'. transliteration_clean_filename(basename($filepath)); // Move the file to a new location but do a shortcut check first to avoid // unneccessary error messages. It's probably better to not mess with // records for missing files. $realpath = realpath($filepath); if ($realpath && file_exists($realpath) && file_move($filepath, $filepath_new, FILE_EXISTS_RENAME)) { // Get the file's new path; it may have changed. $filepath_new = $filepath; // Update the files table with the new path. db_query("UPDATE {comment_upload_files} SET filename = '%s', filepath = '%s', description = '%s' WHERE fid = %d", $filename_new, $filepath_new, $description_new, $file->fid); } else { $errors[] = 'table comment_upload_files: ' . $file->filepath; } } return $errors; }
- Для комментирования войдите или зарегистрируйтесь
После добавления отсутсвующей локали ru_RU.UTF-8 на ubuntu у меня basename не заработал. Точнее, он работал на тестах, а в друпале отказывался. Собака порылась в unique.inc > _unicode_check(). Там выставляется setlocale(LC_CTYPE, 'C');
Т.е. вот этот костыль в bootstrap.inc меня вылечил:
function _drupal_bootstrap($phase) { ... case DRUPAL_BOOTSTRAP_FULL: require_once './includes/common.inc'; _drupal_bootstrap_full(); setlocale(LC_CTYPE, 'ru_RU.UTF-8'); break; ...
- Для комментирования войдите или зарегистрируйтесь
Та же проблема. Решилась выставлением LC_ALL=ru_RU.UTF-8 для апача и комментированием setlocale в unicode.inc
Не понимаю, для чего там сбрасывается локаль на C?
- Для комментирования войдите или зарегистрируйтесь
Просто написали это:
setlocale(LC_CTYPE, 'ru_RU.UTF-8');
вместо
setlocale(LC_CTYPE, 'C');
В unicode.inc.
За транслитерацию получил от начальника по мозгам :(
- Для комментирования войдите или зарегистрируйтесь








Комментарии