У каждой задачи есть несколько вариантов решения. И иногда в угоду скорости приходится выбирать не самый красивый, зато работающий и выполняющий поставленные перед ним цели. Итак, в один не очень прекрасный день возникла необходимость реализовать следующую функцию: у каждой (почти) страницы сайта должны быть автоматически сгенерированные копии в форматах DOC и PDF. С сохранением всех таблиц и картинок внутри контента. И если с PDF всё относительно просто (tcpdf наш друг и брат), то с DOC'ом возникла морока. Под катом — пример решения данной задачи.В голову приходили последовательно такие варианты решения:
Пример применения написанной функции:
А вот и исходный код функции:
Update: в комментариях протестировали получившийся файл — нормально он открывается только в Microsoft Word 2003 и выше, в сторонних продуктах (OpenOffice и другие) возникают проблемы. Так же в комментариях приведены ссылки на многие другие, более правильные методы преобразования
Update 2: Обновил исходник — FlexIDK предложил более удачную регулярку, выбирающую пути картинок без лишних символов.
- Установить на сервер OpenOffice (сервер на FreeBSD) и разобраться с преобразованием. Красивое решение, но время поджимало.
- Сгенерировать вместо DOC'а файлик в формате RTF, благо формат открытый и библиотек для работы с ним много. Минус – готового преобразователя HTML->RTF (с, напомню, сохранением картинок и таблиц) я не нашел, а писать свою – для этого нужен определённый запас времени
- Не очень честный — просто “в лоб” сохранить HTML страницу с расширением DOC – Word 2003 и выше откроет без проблем, проверено. Плюс – отличнейшая скорость преобразования и сохранение всей верстки. Минус – картинки таким образом не сохранить (да и честность метода несколько хромает).
Пример применения написанной функции:
$link="m.habrahabr.ru/post/136811/";
CreateDOC($link,"test.doc");
А вот и исходный код функции:
function CreateDOC($link,$filename)
{
//выделяем базовый домен, пригодится
$base_link=$link;
$base_link=explode("/",$link);
unset($base_link[count($base_link)-1]);
$base_link[]="";
$base_link=implode("/",$base_link);
//получаем текст страницы
$get_text=file_get_contents($link);
//создаём объект, который и будет генерировать нам конечный mht
$MhtFileMaker = new MhtFileMaker();
//подключаем картинки к файлу
//более прямая регулярка, вытаскиваюшая пути картинок, спасибо хабраюзеру FlexIDK
preg_match_all('@<img(.*)?src="([^"]+)"@ui', $get_text, $matches);
foreach ($matches[4] as $img)
{
$img_tmp=$img;
$img_tmp_old=$img;
//помните, базовая ссылка? пригодилась же!
if (strpos($img_tmp,"http")===FALSE)
$img_tmp=$base_link.$img_tmp;
//выделяем путь картинки БЕЗ адреса домена
$img_array=explode("//",$img_tmp);
$img_name_only=$img_array[1];
$img_name_only=explode("/",$img_name_only);
unset($img_name_only[0]);
$img_name_only=implode("/",$img_name_only);
//заменяем адрес картинки на относительный (без домена)
$get_text=str_replace($img_tmp_old,$img_name_only,$get_text);
//добавляем картинку в конечный файлГ
$MhtFileMaker->AddFile($img_tmp, $img_name_only, NULL);
};
//разобрали картинки, теперь создаём окончательный файл
$MhtFileMaker->AddContents("index.html","text/html",$get_text);
//сохраняем файл
$MhtFileMaker->MakeFile($filename);
};
Естественно, можно написать на основе этого гораздо более универсальный и прямой класс, но для наших целей этого было достаточно. Главное — данное решение работает, и достаточно быстро. Надеюсь, оно покажется кому то достаточно полезным.Update: в комментариях протестировали получившийся файл — нормально он открывается только в Microsoft Word 2003 и выше, в сторонних продуктах (OpenOffice и другие) возникают проблемы. Так же в комментариях приведены ссылки на многие другие, более правильные методы преобразования
Update 2: Обновил исходник — FlexIDK предложил более удачную регулярку, выбирающую пути картинок без лишних символов.