2006年10月03日 05:50 [Edit]

perl+javascript - IEでdata:スキームを有効に!

やろうと思えばできるものですねえ。

[JavaScript] dataスキームURI生成(画像データのBase64変換)
残念ながら Internet Explorer は data スキームに対応していないので利用できません。
[を] HTMLファイルに文字列として画像データを埋め込む
表示は IE6 ではだめだけど、Firefox だとOK。

今は亡きMac IEでも見れました。以下、data:スキームによるアイコンが二つ。

要は、中で駄目なら外に出してしまえばいいということです。inside outなので、dataを裏返してatadとしています。

atad.cgi
#!/usr/local/bin/perl -T
#
# $Id: atad.cgi,v 0.1 2006/10/02 20:36:53 dankogai Exp dankogai $
#
use strict;
use warnings;
use MIME::Base64;
use CGI;

sub error{
    print <<"EOT";
Status: 400
Content-Type: text/plain

@_
EOT
    exit();
}

my $q = CGI->new;
my $data = $q->param('data');
error "no data found" unless $data;
$data =~ s{ \A data:  }{}xo;

# http://labs.cybozu.co.jp/blog/kazuho/archives/2006/01/url_base64.php
# http://en.wikipedia.org/wiki/Base64#IRCu
$data =~ tr{[]!*}{+/=;}; 

$data =~ s{ \A (.+?);(.+?), }{}xo;
my ($type, $enc) = ($1, $2);
error "unknown encoding: $enc" unless $enc eq 'base64';
print "Content-Type: $type\n\n", decode_base64($data);

__END__

あとは、こうすればいい。デモが目的なので、ブラウザーチェックはわざと外してあります。FirefoxやSafariでもdata:→http:変換がなされますが、きちんと表示されます。

Client Source:
window.onload = function(e){
    // if (! IE ) return;
    var atad = 'http://www.dan.co.jp/~dankogai/cgi/atad.cgi?data=';
    var safe_b64 = function(str){
      var result = '';
      for (var i = 0; i < str.length; i++){
        var c = str.charAt(i);
        result += ( {'+':'[' , '/':']', '=':'!', ';':'*'}[c] || c);
      }
      return result;
    }
    var elems = document.all || document.getElementsByTagName('*');
    for (var i = 0; i < elems.length; i++){
        var src = elems[i].getAttribute('src');
        if (src && src.indexOf('data:', 0) != -1){
            elems[i].setAttribute('src', atad + safe_b64(src));
            //elems[i].setAttribute('src', atad + encodeURIComponent(src));
        }
    }
}

以下、留意点

  • window.addEventListner()は残念ながらMac IE 5では使えなかったのでwindow.onload()を使用。
  • encodeURIComponent()もIEでは未実装。その代わりに
    Kazuho@Cybozu Labs: URL と Base64
    URL にバイナリデータを埋め込んで渡すことが、ままあります。私のケース注1では、バイナリデータが結構大きかったので hex encode は避けたいところ。 base64 エンコードしようと思ったのですが、 path や query に + や / といった文字は入れたくありません。
    でも紹介されているIRCuでBase64をEncodeしなおしています。
  • 当初はデータをPATH_INFO経由で渡そうとしたのですが、あまり大きなデータだと「path長杉」とApacheに怒られるので、data=data:...としました。

Enjoy!

Dan the Javascripting Perl Monger


この記事へのトラックバックURL

この記事へのトラックバック
  だいーぶ前のDanさんの記事 404 Blog Not Found:perl+javascript - IEでdata:スキームを有効に!   GETでbase64の値を渡してるが、IEだと文字数の制限が入る。*1 大きな画像だったら余裕でそんなもの超えてしまうし、 つまり、ちっちゃなアイコンくらいしか出来ないって
[javascript]やっぱりIEでdata:は無理なんじゃないかという件【へたばるプログラマ日記】at 2007年08月10日 22:57
どうせ大きなURIなら無駄なく大きくしよう! TitanURL.com - lengthen that short URL into a Titan URL
Ajax - 無駄なくでかいURI=IEごめんなさい&gt;&lt;【404 Blog Not Found】at 2007年12月26日 01:40
すでにJavaScriptによるBase64 Encodingの実装は複数あるのですが、これまた気に入った車輪がなかったので再発明。 /lang/javascript/Base64/trunk - CodeRepos::Share - Trac
javascript - Yet Another Base64 transcoder【404 Blog Not Found】at 2008年06月18日 15:59
前々回から紹介している「data URI scheme」を利用する場合、問題になるのは画像を更新するたびに、BASE64などに変換する必要がありました。 めんどくさい、めんどくさすぎます。そんなこといちいちやってられません(涙) そんなあなたのために、指定し画像を全自動でdata sch...
data URI schemeを簡単に運用できる「dataScheme2JS.php」【こーどえいと】at 2010年02月09日 00:04