Проблема с upload'ом файлов с русскими именами

Прислано: Ustas

чт, 05/04/2007 - 14:42

Другие статьи по теме:

Platform: Gentoo Linux (locale: UTF-8) + Apache2 + PHP5 + MySQL
Drupal version: 5.1

Столкнулся с такой проблемой. При добавлении файлов с русскоязычными именами в названии файла отрезается первое слово до первого пробела или символа подчеркивания. В результате IE не может открывать прикрепленные к нодам файлы. В FF все работает.
С англоязычными именами файлов все ок.

На Drupal.org ничего не нашел по этому поводу. Сталкивался ли кто-нибудь с подобной проблемой?

Комментарии


Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Применить"
Опубликовано PVasili в чт, 05/04/2007 - 15:12.

попробкуйте транслитерировать файлы,при сохранении на сервер.
А вообще национальные алфавиты в коммандной строке броузера(без преобразования),а хотят и доменные имена-бред полнейший(imho).
Попробуй найти и отличить mama,мaмa и mамa :)
======================================================
Документация,Дизайн,Переводы


Опубликовано qman в чт, 05/04/2007 - 17:36.

я тоже думал над этой проблемой.
надо бы как то патч написать, чтобы имена файлов в транслите хранились, только ума не хватает и времени разобраться с этим.


Опубликовано PVasili в чт, 05/04/2007 - 17:40.

1 php функция :)======================================================
Документация,Дизайн,Переводы


Опубликовано Ustas в пт, 06/04/2007 - 11:37.

у меня ощущение, что транслитерация должна производиться еще на стороне клиента (если загрузка производится с помощью AJAX'овского интерфейса). Если же транслитерацию делать на стороне сервера, то тогда подскажите, какую функцию использовать - я в стандартной библиотеке PHP такого не помню (только в PECL что-то было, по-моему)..

А вообще, процесс решения проблемы я бы разбил на следующие шаги:

  1. Определить, где происходит потеря первого слова (на стороне клиента или уже на сервере) - для этого надо проанализировать, что приходит из формы на сервер.
  2. В зависимости от того, где происходит потеря слова, добавить преобразование в транслит там, где косяк возникает.

Кто поможет?


Опубликовано Ustas в пт, 06/04/2007 - 14:14.

up


Опубликовано vadbars@drupal.org в пт, 06/04/2007 - 14:31.

Это модуль upload?


Я ставлю строчку "php_value error_reporting 7" в файл .htaccess, а вы? :) Полный русский перевод Drupal 5.x и еще некоторых модулей.


Опубликовано Ustas в пн, 09/04/2007 - 07:58.

Да, видимо, он.


Опубликовано vitamin в вс, 15/04/2007 - 12:40.

Ничего предосудительного в национальных алфавитах в URLе не вижу (с доменными именами, действительно, перебор). Патчить модуль надо на предмет urlencode() и urldecode(), чтоб это работало везде. Ну и разобраться кто первое слово отрезает.
Что-то не нашёл на drupal.org issue по этому поводу. Действительно нет, или плохо искал? Проблема-то, похоже, давняя.


Опубликовано kiev1 в вс, 15/04/2007 - 13:06.

а русские буквы и на диске в некоторых файловых системах плохо сохраняются
поэтому надо взять функцию транслита из pathauto и вставить в upload или еще лучше дописать ее в ядро потому что iconv не всегда правильно работает и не у всех есть


Опубликовано qman в пн, 16/04/2007 - 16:33.

уважаемый kiev1
не могли бы назвать имя функции транслита из pathauto?


Опубликовано kiev1 в пн, 16/04/2007 - 17:23.

function pathauto_cleanstring($string) {


Опубликовано vitamin в вт, 17/04/2007 - 13:37.

значит надо использовать нормальные файловые системы, где проблем с алфавитами нет
а транслитерировать всё - это идиотизм
представьте себе бизнес-портал, на котором собираются люди, не разбирающиеся в компьютерах
и дела им нет ни до каких файловых систем и кодировок
а тут имена файлов (например, msword - сплошь и рядом) преобразуются в транслит
неудобно и неимиджево

ps: поглядел upload.module.. там все строковые ф-ии восьмибитные.. не ожидал, что такое будет в ядре, тем более для некоторых есть врапперы (drupal_strlen, drupal_strtolower и drupal_strtoupper)


Опубликовано Ustas в ср, 18/04/2007 - 09:19.

что будем делать? ;)


Опубликовано vitamin в чт, 19/04/2007 - 08:21.

я запостил репорт на drupal.org, пока тишина..
боюсь, придётся самостоятельно патч писать - им-то что, им юникод не нужен


Опубликовано vitamin в чт, 19/04/2007 - 09:44.

плохи дела
слово отрезает php функция basename, которая криво работает с unicode
см. file.inc ф-ию file_check_upload


Опубликовано vitamin в чт, 19/04/2007 - 11:53.

хм, продолжаем изыскания
basename нормально отрабатывает и ничего не отрезает в случае, если запускать с локалью ru_RU.UTF-8
короче, quick & dirty hack прилагаю


Опубликовано Ustas в пт, 20/04/2007 - 10:03.

Спасибо. Потестирую сегодня и сообщу о результатах. :)


Опубликовано Ustas в пт, 20/04/2007 - 15:02.

Походу, не помогло. Кэш браузера и в базе почистил - нифига. :(


Опубликовано Ustas в пт, 20/04/2007 - 15:24.

Локаль на сервере была выставлена в 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=

Проблема осталась. :( какие еще могут быть варианты?


Опубликовано vitamin в пт, 20/04/2007 - 21:09.

общесистемную локаль нет смысла выставлять, если патч не помог - то и от этого мало толку
в системе, вообще, присутствует локаль ru_RU.UTF-8? команда date чего показывает?
возможно, надо пересобрать php - не знаю точно, где он локали берёт.. или просто положить их ему
попробуй ещё print_r вставить в file.inc в эту ф-ию после basename - может это не он обрезает, хотя вряд ли..


Опубликовано Ustas в пн, 23/04/2007 - 10:35.

Локаль присутствует:

$ 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

Не в этом ли проблема кроется?


Опубликовано vitamin в ср, 25/04/2007 - 08:27.

в phpinfo есть ещё вот что

LANG => ru_RU.UTF-8
_SERVER["LANG"] => ru_RU.UTF-8
_ENV["LANG"] => ru_RU.UTF-8


Опубликовано vitamin в ср, 25/04/2007 - 08:34.

пример, демонстрирующий, что я хочу сказать:

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:~$?>


Опубликовано Ustas в чт, 26/04/2007 - 12:14.

хм-м-м... у меня нет LANG в переменных окружения.. и приведенный пример выдает:

два три
два три


Опубликовано Ustas в пт, 27/04/2007 - 14:31.

Похоже это баг php: http://bugs.php.net/bug.php?id=37945
Обновляю до 5.2.1-r3


Опубликовано qman в пн, 30/04/2007 - 18:54.

обновление помогло?


Опубликовано Ustas в вт, 01/05/2007 - 18:24.

Пока не знаю. Завтра посмотрю - там много зависимостией тянулось, поэтой я в screen'е запустил. О результате сообщу. :)


Опубликовано vitamin в ср, 02/05/2007 - 07:08.

хмм.. странно
у меня 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 в ср, 02/05/2007 - 10:49.

Проблема решилась обновлением. Теперь все ок!
Всем огромное спасибо! :)


Опубликовано qman в чт, 03/05/2007 - 18:13.

уважаемый USTAS не могли бы вы дать описание своих действий а также конфигурации php и OS в которой у вас функционирует сохранение файлов с символами кирилицы???
P.S. большое спасибо.


Опубликовано Ustas в чт, 03/05/2007 - 20:56.

Сервер работает под управлением 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


Опубликовано kiev1 в пт, 04/05/2007 - 06:08.

все равно надо как-то в друпале сделать транслитезацию при аплоаде файлов, потому что очень большая вероятность их потери при неудачном переносе или бекапе (некоторые фтп клиенты, или архиваторы).


Опубликовано dizzz в пт, 19/10/2007 - 08:33.

У меня тоже самое. Как решить эту проблему? ASAP
Версии:
Apache 1.3.37 (Unix)
PHP 5.2.3

Проблема и на этом сервере существует:
имя файла было:
а тут как_эта проблема работает.txt
стало:
тут как_эта проблема работает.txt


Опубликовано kiev1 в пт, 19/10/2007 - 18:14.

ну да, там где локаль utf-8 оно работает вроде нормально, но если юзер начнет копировать кривыми ftp клиентами - то они могут подменить имя файла - а в базе он останется под другим именем - и тогда он не будет находиться.


Опубликовано dizzz в ср, 24/10/2007 - 05:27.

Так что же тогда делать?
Надо как то решать. так жить нельзя на друпале.

В drupal 6.0beta2 проблема остается...


Опубликовано leninsneg в вс, 03/02/2008 - 11:20.

так и нету нормального решения проблемы?


Опубликовано fasdalf@fasdalf.ru в вс, 03/02/2008 - 12:07.

Кто успел попробовать http://drupal.org/project/transliteration ?


Опубликовано bran в пт, 05/12/2008 - 08:28.

после установки модуля http://drupal.org/project/transliteration все заработало как надо


Опубликовано aka в пн, 23/02/2009 - 17:24.

По поводу модуля 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;
}


Опубликовано aka в пн, 23/02/2009 - 17:30.

После добавления отсутсвующей локали 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;
...


Опубликовано hapydoyzer@drup... в ср, 22/07/2009 - 05:18.

Та же проблема. Решилась выставлением LC_ALL=ru_RU.UTF-8 для апача и комментированием setlocale в unicode.inc
Не понимаю, для чего там сбрасывается локаль на C?


Опубликовано Mr.Alinaki@drup... в чт, 13/08/2009 - 08:47.

Просто написали это:

setlocale(LC_CTYPE, 'ru_RU.UTF-8');

вместо
setlocale(LC_CTYPE, 'C');

В unicode.inc.

За транслитерацию получил от начальника по мозгам :(


Ссылки партнёров