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

data URL в IE

Пару лет назад я занимался проблемой data URL в Internet Explorer, добился определённых результатов, но то, что получилось, использовать было невозможно. Data URL (иногда его ещё называют «протокол data:») — возможность вставлять ресурсы (графику, CSS, JavaScript и так далее) в HTML код.

Выглядит это примерно так:

<img
src="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw
AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz
ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp
a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl
ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis
F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH
hhx4dbgYKAAA7" />

В Data URL указывает тип содержимого и способ его кодирования. Способа кодирования два — base64 (именно он и указан в примере), увеличивающий содержимое на треть и URL encoding (в этом случае способ кодирования не указывается) — привычный многим способ кодирования при помощи %xx, в лучшем случае вообще не увеличивает размер содержимого, в худшем — увеличивает в три раза.

Кстати, в настоящее время IE8b1 поддерживает data URL, но, увы, длиной не более 32Кб.

Теперь амбула.

Вчера ночью мне пришла в голову идея как можно попытаться корректно совместить data URL и включение картинок через протокол mhtml. То, что у меня не получилось два года назад, получилось сейчас.

Результат — готовый код на PHP из двух функций. Первую функцию («bolk_data_uri_header») нужно вызвать в самом начале перед выводом любого вашего кода, вторую («bolk_data_uri») собственно для включения картинки в код. Надеюсь на примерах всё понятно:

bolk_data_uri_header();

bolk_data_uri('myjpeg.jpg');
bolk_data_uri('ourpng.png', 'border: 2px dotted red');

Код самой библиотеки:

function bolk_data_uri_header()
{
    echo "<!--\n"
        ."Content-Type: multipart/related; boundary=\"=_NextPart_01C6A9B1.539AB070\"\n\n"
        ."--=_NextPart_01C6A9B1.539AB070\n"
        ."Content-Transfer-Encoding: base64\n"
        ."Content-Type: text/html\n"
        ."-->\n\n";

}

function bolk_data_uri($file, $style = '')
{
    if (!( file_exists($file) && ($data = @getimagesize($file)) )) return false;

    $name = uniqid('', true);

    if ($style <> '') $style = ' style="'.htmlspecialchars($style).'"';

    echo "<!--\n"
        ."--=_NextPart_01C6A9B1.539AB070\n"
        ."Content-Location: {$name}\n"
        ."Content-Transfer-Encoding: base64\n"
        ."Content-Type: {$data['mime']}; -->\n"
        ."<object data='data:{$data['mime']};base64,\n\n";

    echo base64_encode(file_get_contents($file));

    echo "' {$data[3]}{$style} type='\n{$data['mime']}'><img "
        ."src='mhtml:http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}!{$name}' {$data[3]}{$style} /></object>\n\n"
        ."<!--\n"
        ."--=_NextPart_01C6A9B1.539AB070-->";

    return true;
}

У данного метода, по сравнению с обычными data URL есть масса ограничений: необходим специальный заголовок в начале файла, т. е. этот метод невозможно использовать на чужих сайтах, этим методом нельзя воспользоваться (по крайней мере не в таком виде) для включения ресурсов внутрь CSS или JavaScript. В принципе, тут есть достаточно большое поле для экспериментов, возможно все или некоторые из проблем можно решить.

В разделе «храню» есть пример, который можно потестировать на имеющихся у вас браузерах. Уже протестировано на Opera 9.25 и 9.50b, FF 2.0.0.13 и 4 (Minefield), Safari 3.1 (Safari под iPhone — тоже), Internet Explorer 6.0SP2 и 7.0, Sony PSP browser, Opera mini, Netscape Navigator 9.0.0.5.

30 комментариев
Sam Dark (Sam.Dark.myopenid.com) 2008

Проверено в Opera 9.25, IE7, FF4(Minefield).

Евгений Степанищев (bolknote.ru) 2008

Комментарий для sam.dark.myopenid.com:

Спасибо, занесу!

xplay (openid.yandex.ru/users/xplay) 2008

Супер. Ура первооткрывателю =)

Евгений Степанищев (bolknote.ru) 2008

:)

Sas (mmasco.myopenid.com) 2008

IE6 SP1 — не работает.

blog.ad.by 2008

Комментарий для Евгения Степанищева:

Я погонял на всем что входит в MultipleIEs: 4.01, 5.01, 5.55, 6.0. Работает везде, только мой опыт говорит что верить этому нужно с осторожностью: например, VML в нормальном 5.01 работает, а в этом комплекте на 5.01 — нет.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для mmasco.myopenid.com:

Полная версия подопытного? У меня работает (только что посмотрел) на IE6.0.2900.2180.xpsp_sp2_rtm.040803-2158.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для blog.ad.by:

Спасибо, но, да на MultipleIE данные могут отличаться.

u1itka.livejournal.com 2008

А что там должно быть? Если пиктограмма «лист бумаги», то на Safari в iPhone тест пройден.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для u1itka.livejournal.com:

Она и должна быть, спасибо.

Sas (mmasco.myopenid.com) 2008

Комментарий для Евгения Степанищева:

Version:6.0 2800.1106 Update version: SP1

Евгений Степанищев (bolknote.ru) 2008

Комментарий для mmasco.myopenid.com:

Дико забавно. А что выдаёт? Крестик? mht нормально показывает?

Sas (mmasco.myopenid.com) 2008

Точку в квадратике выдает :)
http://calc.ugh.ru/mhtml.gif

Евгений Степанищев (bolknote.ru) 2008

Комментарий для mmasco.myopenid.com:

А! Это должно быть тег OBJECT, а можно вас по аське помучать? Я думаю можно попробовать в conditional comments всё это сунуть.

ICQ# 2-99-3333

arikon.livejournal.com 2008

Женя, в FF 3.0.1 под Mac OS X работает, а в Safari 3.1.2 (5525.20.1) — не работает, показывает только квадратик без иконки.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для arikon.livejournal.com:

А этот?
http://bolknote.ru/files/ie-data-url-2.php

arikon.livejournal.com 2008

Комментарий для Евгения Степанищева:

А этот работает. И в Windows тоже (первое решение в Safari под Windows тоже не работало).

Опубликуй исходник нового решения.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для arikon.livejournal.com:

«Новый» исходник ровно такой же как и старый, просто отделение IE сделано через conditional comments.

molder.moikrug.ru 2008

Комментарий для Евгения Степанищева:

вот оно, счастье!

id.rambler.ru/users/danyv/ 2009

При использовании данного решения с протоколе https в IE есть проблема с security warning: http://iescripts.org/view-scripts-464p1.htm (не важно как реализовано: как в примере через JavaScript или через mhtml). Может быть кто-то встречался и решил эту проблему?

Евгений Степанищев (bolknote.ru) 2009

Комментарий для id.rambler.ru/users/danyv/:

mhtml:https не спасает?

rakeev.livejournal.com 2009

В Firefox тоже появляется «соединение частично зашифровано»
Обидно, из-за этого придется от data:uri отказаться :(

Евгений Степанищев (bolknote.ru) 2009

Комментарий для rakeev.livejournal.com:

Правда? Вот это уже удивительно. А какая версия FF?

sillysunnybear.livejournal.com 2009

Эту ошибку в Fx вроде исправили (почти год мучили)

Евгений Степанищев (bolknote.ru) 2009

Комментарий для sillysunnybear.livejournal.com:

Пытаешься говорить как положено? «Fx»? :)

А в какой версии исправлено?

Павел 2010

тут http://www.websiteoptimization.com/speed/tweak/inline-images/folder-testcss.html и тут http://bolknote.ru/files/ie-data-url.php у меня в ie 8.0.7600.16385 картинки data url не показываются! Тестил в 32х и 64х битном 8ие, windows 7 лицензионный, постоянно обновляется.

Евгений Степанищев (bolknote.ru) 2010

Комментарий для Павел:

Посмотрите вот тут: http://bolknote.ru/files/ie-data-url-2.php

Давал же ссылку уже в комментариях.

search-bot.net 2011

Не работает в ИЕ. Vista Sp2

Евгений Степанищев (bolknote.ru) 2011
Руслан 2013

*Большое спасибо!*
Я надеюсь Вы в скором будущем займетесь разработкой ОС! И быть может мы увидим отличную Операционную систему.
Мои пожелания: попробуйте себя в написании ОС!
Может быть Вы будущий Билли. Я буду очень рад если Вы его превзойдете!
Еще раз спасибо Вам за проделанный труд!
Моя почта для связи: eWFuZGV4LnJ1QFdlYlJvY2tlZmVsbGVy