Проблеми з кирилицею при распоковке zip-архівів за допомогою php (скрипт PclZip)
Даний глюк виявив на роботі, коли менеджери почали скаржитися, що одна з функцій самопісний CMS не працює. Почавши розбиратися я виявив, що одна з папок, в яку php-скрипт переміщував розпаковані з zip-архіву файли, постійно забивалася якимось сміттям (файлами з незрозумілою кодуванням, у яких замість букв - квадратики та інші недоноски).
Скрипт полягав в наступному: розпаковував файли з архіву, проробляв над ними махінації і потім видаляв їх. Те-є папка не повинна була нічим заповнюватися. Я перевірив скрипт - все здавалося в порядку. Спробував видалити ці файли за допомогою файлового менеджера - не вийшло:
А адже саме через ці сміттєвих файлів і відмовила функція, на яку скаржилися менеджери. Написав в службу підтримки хостингу - вони їх видалили.
усунення проблеми
Звичайно ж все виявилося дуже просто. Для розпакування файлів використовувалася php-бібліотека "PclZip". Відкриваємо її і бачимо функцію privReadCentralFileHeader, в якій присутній наступний код:
// ----- Get filename
// - (MAGIC-PclTrace) - // PclTraceFctMessage (__ FILE__, __LINE__, 4, "File name length:". $ P_header [ 'filename_len']);
if ($ p_header [ 'filename_len']! = 0)
{
$ P_header [ 'filename'] = fread ($ this-> zip_fd, $ p_header [ 'filename_len'];
}
else
$ P_header [ 'filename'] = '';
Все що нам необхідно - перекласти назву файлу в потрібну нам кодування. У моєму випадку це була UTF-8, тому я виправив рядок отримання імені файлу ось на таку:
$ P_header [ 'filename'] = iconv ( "866", "UTF-8", fread ($ this-> zip_fd, $ p_header [ 'filename_len']));
Після цього все стало працювати коректно. Глюки нарешті зникли (як виявилося, їм було вже близько року ^^).
Видалення з сервера файлів з порушеною кодуванням в імені
А як же видалити файли з порушеною кодуванням, якщо при будь-якій спробі це зробити файловий менеджер видає помилку "неможливо видалити файл"? Я знайшов таке рішення: написав простенький php-скрипт, який обходить всі файли в папці, бере їх імена і видаляє з сервера (функція unlink).
Якщо потрібно видалити вибірково, то можна видаляти всі файли, імена яких містять символи, код яких знаходиться в заданому інтервалі (які саме межі інтервалу використовувати визначте самі). Якщо файли потрібні, то їх можна перейменувати в нормальні випадкові імена, або навіть в їх реальні імена, використовуючи все ту ж функцію iconv.
Коментарі (4)
Порядок виведення коментарів:
3. Кирило 23.11.2011 12:31
Відповідь: Ні, все працювати буде)) просто буде працювати тільки на Windows.
Я думаю потрібне місце в коді ти вже знайшов. Залишилося перекодувати, але не як в прикладі цієї статті: у твоєму випадку там буде фігурувати 'windows-1251'. Пограйся з 866, win і utf, всього 4 комбінацій різних за участю кодування win =) Там все-таки від коду залежить, конкретно не можу підказати що будь-що кодувати, тому раджу перебір ось такий. + Раджу використовувати зневаджувальної в файл і в якомусь notepad ++ дивитися - там кодування можна на ходу швидко міняти.