WordPress как на ладони
wordpress jino

Исправление сломанных названий кириллических файлов-картинок в папке uploads

Здравствуйте.

Есть сайт на котором раньше загружались картинки с кириллическими названиями фалов. Теперь я перенес этот сайт на другой хостинг и все названия картинок где есть кириллица поломались.

Было: картинка.jpg, стало картинка.jpg.

Таких поврежденных картинок у меня много и исправлять их вручную практически нереально...

Помогите пожалуйста это поправить, как-то пакетно с помощью скрипта.

Я в PHP немного разбираюсь, не сложные коды могу править.

0
Гость 1.6 года назад
  • 0
    Kama4639

    Я как-то сталкивался с таким ниже выложу код которым я это поправил.

    Но для начала замечу: названия файлов желательно хранить в латинице всегда! Так проблем меньше. И если даже загружается файл с кириллицей в названии, то название налету должно менять на латиницу, как это происходит при использовании плагина cry-to-lat, кстати в плагине Cyr to Lat enhanced этот момент учтен и если использовать его, то у таких проблем не будет.

    Этот код переделывает кириллические названия в латиницу...

    Код, который я написал для исправления таких файлов разделен на части. Для его использования надо понимать PHP, хотя бы на уровне того что примерно происходит и если надо кое-где подправить под себя или для проверки... Если использовать код сразу без проверок и понимания что происходит, то последствия могут быть неожиданными...

    Перед использованием кода, обязательно сделайте бэкап всего что можно... Далее запускайте каждую часть отдельно и смотрите все ли делается правильно...

    Для вызова каждой части добавляйте в URL GET параметр: например первая часть вызывается так: site.ru?repair_files.

    <?php
    
    /**
     * ЧАСТЬ 1: ремонтирует поломанные названия кириллических файлов в папке uploads.
     * Когда файл выглядит так: Дом_РёР·_клеёного_Р±СЂСѓСЃР° - это 'cp-1251'
     */
    if( isset($_GET['repair_files']) ){
    	// настройки
    	$maindir = wp_upload_dir();
    
    	$debug = 1;
    	// проверка - $debug
    	// Прежде чем запускать, закиньте один файл в папку uploads и запустите эту проверку, этот файл должен переименоваться.
    	// Если все работает, то выключаем debug, удаляем проверочный файл и запускаем полное переименование - это может занять время. Для работы с большим объемом файлов скрипт не рассчитан...
    
    	if( $debug ){
    		foreach( glob( $maindir['basedir'] ."/*") as $fname ){
    			if( is_file($fname) ){
    				echo var_dump( __repair_cyrilic_filenames_rename( $fname ) );
    				echo ' - '. dirname($fname) .' - '. basename( $fname ) ."<br>\n";
    			}
    		}
    		die('КОНЕЦ');
    	}
    
    	// запускаем полное переименование в папке uploads
    	if( ! $debug ){
    		repair_cyrilic_filenames( $maindir['basedir'] );
    		die('КОНЕЦ');
    	}
    }
    // функции
    function repair_cyrilic_filenames( $dir ){
    	if( is_dir($dir) ){
    		foreach( glob("$dir/*") as $fname ){
    			call_user_func( __FUNCTION__, $fname ); // рекурсия
    		}       
    	}
    	//repair
    	elseif( is_file($dir) ){    
    		echo __repair_cyrilic_filenames_rename( $dir ) ? 'ОК - ' : 'ERROR - ';
    		echo $dir ."<br>\n";
    	}
    
    }
    function __repair_cyrilic_filenames_rename( $fname ){
    	$new_fname = mb_convert_encoding( $fname, 'cp-1251', 'utf-8');
    	return @ rename( $fname, $new_fname );
    }
    
    /**
     * ЧАСТЬ 2: транслитерация названий файлов в каталоге
     */
    if( isset($_GET['sanitize_file_name_in_dir']) ){
    	// запуск
    	$maindir = wp_upload_dir();
    	sanitize_file_name_in_dir( $maindir['basedir'] );
    
    	die('КОНЕЦ');
    }
    function sanitize_file_name_in_dir( $dir ){
    	if( is_dir($dir) ){
    		foreach( glob("$dir/*") as $fname ){
    			call_user_func( __FUNCTION__, $fname ); // рекурсия
    		}       
    	}
    	//repair
    	elseif( is_file($dir) ){
    		if( preg_match( '~[^/]+$~', $dir, $m ) ){
    			$_fname = $m[0];
    			$_dir   = str_replace( $_fname, '', $dir );
    
    			$_fname = mb_convert_encoding( $_fname, 'utf-8', 'cp-1251');
    			$_fname = sanitize_file_name( $_fname );
    
    			if($_fname){
    				$new_fname = $_dir . $_fname;
    				if( ($dir != $new_fname) && @ rename( $dir, $new_fname ) )      
    					echo 'OK - '. $dir .' >>> '. $new_fname ."<br>\n";
    				else
    					echo 'ERROR - '. $dir .' >>> '. $new_fname ."<br>\n";                
    			}
    		}
    	}
    }
    
    /**
     * ЧАСТЬ 3: транслитерация названий файлов в базе данных
     */
    if( isset($_GET['sanitize_filename_in_db']) ){
    	sanitize_filename_in_db();
    
    	die('КОНЕЦ');
    }
    function sanitize_filename_in_db(){
    	global $wpdb;
    
    	$ress = $wpdb->get_results("SELECT ID, guid FROM $wpdb->posts WHERE post_type = 'attachment' AND guid LIKE '%uploads%'");
    	if( $ress ){
    		foreach( $ress as $item ){
    			if( ! preg_match( '~[^/]+$~', $item->guid, $m ) )
    				continue;
    
    			$_fname = $m[0];
    			$_pre = str_replace( $_fname, '', $item->guid );
    
    			$_fname = sanitize_file_name( $_fname );
    			$new_guid = $_pre . $_fname;
    
    			if( $item->guid != $new_guid ){
    				$done = $wpdb->query(
    					$wpdb->prepare("UPDATE $wpdb->posts SET guid = %s WHERE ID = %d", $new_guid, $item->ID )
    				);
    
    				echo ($done ? "OK - $item->guid >>> $new_guid" : "ERROR - $item->guid") ."<br>\n";
    			}
    		}
    	}
    
    	// поправим данные в метаданных
    	//_wp_attached_file
    	$ress = $wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file'");
    	if( $ress ){
    		foreach( $ress as $item ){
    			if( ! preg_match( '~[^/]+$~', $item->meta_value, $m ) )
    				continue;
    
    			$_fname = $m[0];
    			$_pre = str_replace( $_fname, '', $item->meta_value );
    
    			$_fname = sanitize_file_name( $_fname );
    			$new_guid = $_pre . $_fname;
    
    			if( $item->meta_value != $new_guid ){
    				$done = $wpdb->query(
    					$wpdb->prepare("UPDATE $wpdb->postmeta SET meta_value = %s WHERE meta_id = %d", $new_guid, $item->meta_id )
    				);
    
    				echo ($done ? "OK - $item->meta_value >>> $new_guid" : "ERROR - $item->meta_value") ."<br>\n";
    			}
    		}   
    	}
    
    	// поправим данные в метаданных
    	// _wp_attachment_metadata
    	// для этого лучше использовать плагин Forse Regenerate Thumbnails
    }
    
    /**
     * ЧАСТЬ 4: транслитерация URL картинок из папки /uploads/ в контенте записи
     */
    if( isset($_GET['sanitize_filename_in_post_content']) ){
    	sanitize_filename_in_post_content();
    	die('КОНЕЦ');
    }
    
    function sanitize_filename_in_post_content(){
    	global $wpdb;
    
    	$ress = $wpdb->get_results("SELECT * FROM $wpdb->posts WHERE post_status = 'publish' AND post_content LIKE '%/uploads/%'");
    	$out = '';
    	foreach( $ress as $post ){
    		$_out = array();
    		$_out[] = $post->post_title . ' - '. get_permalink($post->ID) ."\n\n";
    
    		preg_match_all('~/uploads/[^"\']+~', $post->post_content, $mm );
    
    		foreach( $mm as $arr ){
    			$echo_out = false;
    
    			foreach( $arr as $url ){
    				preg_match( '~[^/]+$~', $url, $m );         
    				$_fname = $m[0];
    				$_pre = str_replace( $_fname, '', $url );
    
    				$_fname = sanitize_file_name( $_fname );
    				$new_url = $_pre . $_fname;
    
    				// заменяем
    				if( $url != $new_url ){
    					$wpdb->query("UPDATE $wpdb->posts SET post_content = REPLACE(post_content, '$url', '$new_url') WHERE ID = $post->ID");
    
    					$echo_out = true;
    					$_out[] = $new_url ."\n";
    				}
    			}
    		}
    
    		echo $echo_out ? implode('',$_out)."\n\n" : '';
    	}
    }
    
    /**
     * ЧАСТЬ 5 (если надо): исправление размеров после регенерации миниатюр (forse-regenerate).
     * Некоторые файлы, например, имели размер 300-200 а стали 300-201
     */
    if( isset($_GET['fix_sizes_after_force_regenerate']) ){
    	fix_sizes_after_force_regenerate();
    	die('КОНЕЦ');
    }
    
    function fix_sizes_after_force_regenerate(){
    	global $wpdb;
    
    	$upload_dir_path = wp_upload_dir()['basedir'];
    
    	$ress = $wpdb->get_results("SELECT * FROM $wpdb->posts WHERE post_status = 'publish' AND post_content LIKE '%/uploads/%'");
    	$out = '';
    	$i=1;
    	foreach( $ress as $post ){
    		$_out = array();
    		$_out[] = $post->post_title . ' - '. get_permalink($post->ID) ."\n\n";
    
    		preg_match_all('~/uploads/[^"\']+~', $post->post_content, $mm );
    
    		foreach( $mm as $arr ){
    			$echo_out = false;
    			foreach( $arr as $url ){
    				$fpath = $upload_dir_path . str_replace('/uploads','',$url);
    
    				if( ! file_exists($fpath) ){
    					//$echo_out = true;
    					//$_out[] = $i++ .' - '. $fpath ."\n";
    
    					// получим все имеющиеся размеры файла
    					$fpath_patt = preg_replace('~-[0-9]+x[0-9]+(?=\.jpg|\.jpeg|\.png|\.gif)~', '*', $fpath );
    
    					//echo $fpath_patt;
    					//print_r( glob( $fpath_patt ) );
    
    					// удалим неподходящие размеры и получим нужный, он там один
    					$new_fpath = '';
    					foreach( glob( $fpath_patt ) as $pth ){
    						if( preg_match('~80x80~',$pth) ) continue;
    						if( ! preg_match('~-[0-9]+x[0-9]+\.(jpg|jpeg|png|gif)~',$pth) ) continue;
    						$new_fpath = $pth;
    
    						// удалим лишнюю начальную часть и заменяем все в контенте
    						$old_url = preg_replace('~^.*?/uploads/~','/uploads/', $fpath);
    						$new_url = preg_replace('~^.*?/uploads/~','/uploads/', $new_fpath);
    
    						$echo_out = $wpdb->query("UPDATE $wpdb->posts SET post_content = REPLACE(post_content, '$old_url', '$new_url') WHERE ID = $post->ID");
    
    						//$echo_out = true;
    						$_out[] = $old_url . ' - '. $new_url ."\n";
    					}
    				}               
    
    			}
    		}
    
    		echo $echo_out ? implode('',$_out)."\n\n" : '';
    	}
    }
    
    Комментировать
На вопросы могут отвечать только зарегистрированные пользователи. Регистрация. Вход.