Перехват нужного типа файлов web-сервером или разбор FB2 на PHP
Представим, что нам нужно выводить в браузере файл некоторого формата, обращаясь к нему по прямому URL, то есть, переход по ссылке
http://localhost/fb2/test.fb2
будет означать обработку и вывод в браузер файла test.fb2
, находящегося в папке fb2
на локальном сервере. Так как сам браузер отображать формат FB2 не умеет, нам придётся передавать такие файлы на обработку какому-то скрипту, написанному на PHP или другом серверном языке.
Для простоты предположим, что все файлы нужного формата собраны в одной папке. В таком случае решением будут всего 2 строки в файле .htaccess, который мы поместим в эту же папку:
AddDefaultCharset utf-8 RewriteEngine On RewriteRule ^(.*).fb2$ index.php?f=$1 [L]
Вместо fb2
можно вписать другой тип файла, а вместо f
- другое имя параметра URL-запроса.
Осталось реализовать файл index.php
, который будет разбирать и выводить в браузер переданный ему FB2. Ниже приводится простой вариант разбора FB2 на PHP, основанный на том, что FB2 представляет собой обычный XML-файл.
Показанный код не является корректным разбором формата FB2 и просто демонстрирует подход к решению этой задачи. Тестовый файл .fb2
я взял вот отсюда и основное его содержимое скрипт всё же вывел :)
Предполагается, что сам скрипт и отображаемые файлы FB2 закодированы в Юникоде (UTF-8).
Выводимые на страницу картинки у нас для простоты пишутся прямо в папку скрипта, в реальном решении такой подход не годится. Также в сети есть гораздо более мощные решения для разбора формата FB2, например, здесь, но с их установкой и настройкой всё равно придётся повозиться.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>FB2 file</title> </head> <body> <?php class fictionbook { public $book; public $table_of_content = array(); public $book_info = array(); function book_load ($file) { if (file_exists($file)) { $this->book = simplexml_load_file ($file); if ($this->book === false) { exit ('<p>Неверная разметка XML в файле '.$file.'</p>'); } $this->title_info(); } else { exit('<p>Не удалось открыть файл '.$file.'</p>'); } } function title_info (){ $title_info = 'title-info'; foreach ($this->book->description->$title_info->children() as $key=>$children) { switch ($key) { case 'genre': $this->book_info['genre'][] = $children; break; case 'book-title': $this->book_info['book-title'] = $children; break; case 'author': $last_name = 'last-name'; $first_name = 'first-name'; $middle_name = 'middle-name'; $home_page = 'home-page'; $this->book_info['author'][] = array ( 'first-name'=>$children->$first_name, 'middle-name'=>$children->$middle_name, 'last-name'=>$children->$last_name, 'home-page'=>$children->$home_page, 'email'=>$children->email ); break; case 'annotation': $this->book_info['annotation'] = $children->asXML(); break; case 'coverpage': $this->book_info['coverpage'] = $children->image; break; case 'date': $this->book_info['date'] = $children; break; case 'translator': $last_name = 'last-name'; $first_name = 'first-name'; $middle_name = 'middle-name'; $home_page = 'home-page'; $this->book_info['translator'][] = array ( 'first-name'=>$children->$first_name, 'middle-name'=>$children->$middle_name, 'last-name'=>$children->$last_name, 'home-page'=>$children->$home_page, 'email'=>$children->email ); break; case 'lang': $this->book_info['lang'] = $children; break; case 'year': $this->book_info['year'] = $children; break; } } $this->table_of_content = $this->table_of_content(); } function print_image ($image) { $image = $image->asXML(); preg_match("/[\"|\']\#([\S]+\.[\S]+)[\"|\']/i", $image, $image_name); $image_name = $image_name[1]; foreach ($this->book->binary as $binary){ if ($binary[id] == $image_name){ $image = base64_decode($binary); //Пишем файл прямо в папку скрипта - так делать не надо! $file = fopen($image_name, 'w'); fwrite($file, $image); fclose($file); echo '<img src="'.$image_name.'">'; } } } function table_of_content ($book=false) { if (!empty($this->table_of_content)) { return $this->table_of_content; } if ($book === false){ $book = $this->book->body; } foreach ($book as $key=>$body) { if (isset($body->title)) { $title = $this->clear_string($body->title->asXML()); if (!empty($title)) { $title_array[] = $title; } } $title_array_temp = $this->table_of_content($body->section); if (!empty($title_array_temp)){$title_array[] = $title_array_temp;} } return $title_array; } function content ($book=false, $i=-1) { if ($book === false) { $book = $this->book->body; } ++$i; foreach ($book->children() as $key=>$body) { switch ($key) { case 'image': $this->print_image ($body); break; case 'title': if ($i == 0) $i=1; $title = $this->clear_string($body->asXML()); echo ''.$title; break; case 'section': $this->content($body, $i); break; case 'epigraph': echo ''.$this->clear_string($body->asXML()).''; break; default: echo $this->clear_string($body->asXML(), false); break; } } } function print_table_of_content ($table = false) { if (!$table) { $table = $this->table_of_content; } foreach ($table as $row) { if (is_array($row)) { $this->print_table_of_content($row); } else { echo ''.$row; } } } private function clear_string ($string, $p = true) { $string = preg_replace('/\|\<\/title\>/im', '', $string); $string = preg_replace('/\s+/m', " ", $string); $string = preg_replace('/^\s+|\s+$/', '', $string); if ($p) $string = preg_replace('/\|\<\/p\>/im', '', $string); return $string; } } libxml_use_internal_errors(true); //Отключили встроенный контроль ошибок XML! $book = new fictionbook; if (!isset($_GET['f'])) { exit ('<p>Не передано имя файла .fb2</p>'); } $fname = basename(htmlspecialchars(trim($_GET['f']))); $book->book_load($fname.'.fb2'); $book->print_table_of_content(); $book->content(); ?> </body></html>
04.04.2018, 12:41 [2936 просмотров]