« XMLHttpRequestでファイルをDataSchemeで取得する実験 その2 | メイン | Canvasを利用して画像データをBase64で取得する時の制限 »

XMLHttpRequestでファイルをDataSchemeで取得する実験 その3

1entryの容量を超えたので分割。その2からの続き。
00:25
Wassr経由で教えてもらった情報を忘れていた。
リモートの画像をdata schemeな形で取得したいのなら、Canvas使うのが簡単
var cx=Canvas.getContext(...);
var img=new Image();
img.src="..";
cx.drawImage(img, ...);
cx.toDataURL();
こっちもこっちで凄い。グリモンの例では、GM_xmlhttpRequestを使ってクロスドメインでデータを取得している。しかし、Canvasを使った方法では、画像に限定されるけどURLを直接指定しているので同一出身ポリシーを気にする必要はない。これは凄いわ。
2009/04/15 追記
クロスドメインは不可能でした。これについて続きを書きました。
00:39
Base64関数をbtoaに置き換えた。
// ==UserScript==
// @name        getFileByDataScheme
// @namespace   http://www.kanasansoft.com/
// @include     *
// ==/UserScript==

(
    function(){

        var parseHTTPHeader=function(responseHeader){
            var headers=responseHeader.split("\n");
            var len=headers.length;
            var parsing=[];
            for(var i=0;i<len;i++){
                if(/^$/.test(headers[i])){
                }else if(/^[\x09\x20]/.test(headers[i])){
                    if(parsing.length==0){
                        throw "SyntaxError:HTTPHeader (first line) "+headers[i];
                    }
                    parsing[parsing.length-1]+="\n"+headers[i];
                }else{
                    parsing.push(headers[i]);
                }
            }
            var len=parsing.length;
            var parsed={};
            for(var i=0;i<len;i++){
                var pair=parsing[i].split(": ",2);
                if(pair.length!=2){
                    throw "SyntaxError:HTTPHeader (format) "+parsing[i];
                }
                if(pair[0] in parsed){
                    throw "SyntaxError:HTTPHeader (repetition) "+pair[0];
                }
                parsed[pair[0]]=pair[1];
            }
            return parsed;
        }

        var loadDataMethod=function(res){
            var headers=parseHTTPHeader(res.responseHeaders);
            if(res.status!=200){
                throw "RequestError"+
                    ":status="+res.status+
                    ":statusText="+res.statusText+
                    ":responseHeaders="+res.responseHeaders;
            }
            var contentType=("Content-Type" in headers)?
                headers["Content-Type"]:
                "application/octet−stream";
            var dataScheme="data:"+contentType+
                ";base64,"+btoa(
                    res.responseText.replace(
                        /[\u0100-\uffff]/g,
                        function(c){
                            return String.fromCharCode(c.charCodeAt(0)&0xff);
                        }
                    )
                );
            data.callback(dataScheme);
        }

        var getData=function(url){
            data.url=url;
            GM_xmlhttpRequest(
                {
                    "method":"GET",
                    "url":data.url,
                    "onload":loadDataMethod,
                    "onerror":loadDataMethod,
                    "overrideMimeType":"text/plain; charset=x-user-defined"
                }
            );
        }

        var data={};

        var getFileByDataScheme=function(url,callback){
            data.callback=callback;
            getData(url);
        }

        if(window.self==window.top){
            var url=prompt("image url","");
            if(url==null||url==""){
                return;
            }
            var handler=function(url,callback){
                return function(){
                    getFileByDataScheme(url,callback);
                }
            }
            var callback=function(dataScheme){
                var elem=document.createElement("img");
                elem.src=dataScheme;
                document.body.appendChild(elem);
            }
            window.addEventListener(
                "load",
                handler(url,callback),
                false
            );
        }

    }
)();
実際に動作させるために無駄な処理が入っているけど、データ取得からBase64化までだともの凄く短い。
まとめ
XMLHttpRequestやGM_xmlhttpRequestでは文字列だけではなく、binaryを取得することができる。JavaScriptでBase64化することも可能。GreasemonkeyのGM_xmlhttpRequestではサーバが異なってもデータを取得できる。Greasemonkeyは、文字列を保存することが可能なのでBase64化しさえすれば、容量の問題はあるけど保持し続けることもできる。UserScript内でなくても、画像ファイルであればサーバを超えてBase64で取得することが可能。
感想
知らなかったけど、これは非常に応用範囲が広いと思う。binaryを扱うことができるので、画像であればJPEGやPNGの変換もJavaScriptで可能になるし、複数のファイルを指定してzipで圧縮なんかも可能になる。多分すでにあるんだろうけど今の段階でもJavaScriptだけでいろんなことができる。後はアイディア次第だと感じた。
謝辞
名前をだすことの了承を得ていないのでHNは出していませんが、色々なところで支援を頂いた皆様、ありがとうございました。
2009/04/15 追記
ここで終わるつもりだったのですが続きます。

トラックバック

このエントリーのトラックバックURL:
http://www.kanasansoft.com/cgi/mt/mt-tb.cgi/217

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

Google