2009/02/23

Recent entries from same category

  1. xtag と angular1 を足して2で割った感じに使える薄い JavaScript ライブラリ「sj.js」
  2. Web Component を簡単に作れる JavaScript ライブラリ「X-Tag」
  3. twitter.bat
  4. jQueryプラグインとして動作するGithub Badge作ってみた。
  5. XSLとjQuery/HTMLだけで作る、amazon最速検索

WassrのAPIには、imageパラメータによる画像アップロードがあるのですが、これに困ってる人がいたので、人助け。
Wassr [お気軽メッセージングハブ・ワッサー]

質問です。Firefox の Live HTTP Headers で確認すると Web のフォームから画像をアップロードすると素のバイナリデータが送信されています。API を利用した POST でも素のバイナリデータで送信しなければならないのでしょうか?

http://wassr.jp/channel/wassr_api/messages/hNHcDCCtja

試しにvimperatorから出来ないか挑戦してたらハマってハマって...色々試してたんですが、どうも画像だけがアップロードされない。
送信データを以下の様な関数で保存して目で確認してみたけど、あってる。
function writeToFile (filePath, content) {
    try {
        netscape.security.PrivilegeManager.enablePrivilege ('UniversalXPConnect');
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance (Components.interfaces.nsILocalFile);
        file.initWithPath (filePath);
        if (! file.exists ()) file.create (0, 0664);
        var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance (Components.interfaces.nsIFileOutputStream);
        out.init (file, 0x20 | 0x02, 00004, null);
        out.write(content, content.length);
        out.close();
    } catch (e) {
        throw e;
    }
}
で、最後の最後は自前でCGIを立ててデータを確認してみた所、なんとデータが欠けてる!!

もしかしてsendじゃ送れないんじゃないか?と思ったらXMLHttpRequestにsendAsBinaryなんてメソッドがあった。
XMLHttpRequest - MDC
This method was added in Firefox 3.

A variant of the send() method that sends binary data.

void sendAsBinary(
  in DOMString body
);
Parameters

body

The request body as a DOM string. This data is converted to a string of single-byte characters by truncation (removing the high-order byte of each character).

https://developer.mozilla.org/en/XMLHttpRequest#sendAsBinary%28%29
はよ言えや!

見事送信する事が出来ました。
function createMultipartData(data, boundary) {
    var ret = [], boundary = "BOUNDARY-" + (boundary||'')+Math.floor(0x1000000 + Math.random() * 0xffffff).toString(16);
    for (var item in data) {
        if (!data.hasOwnProperty(item)) continue;
        var obj = data[item];
        if (obj.filename) {
            ret.push(
                '--' + boundary,
                'Content-Type: '+obj.contentType,
                'Content-Length: '+obj.content.length,
                'Content-Disposition: form-data; name="'+item+'"; filename="'+obj.filename+'"',
                'Content-Transfer-Encoding: binary',
                '',
                obj.content
            );
        } else {
            ret.push(
                '--' + boundary,
                'Content-Disposition: form-data; name="'+item+'"',
                '',
                String(obj)
            );
        }
    }
    ret.push('--' + boundary + '--', '');
    return {
        contentType : "multipart/form-data; boundary=" + boundary,
        content: ret.join("\n")
    };
}


function getFileContents(aFilePath) {
    var file = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
    file.initWithPath(aFilePath);
    var fstream = Components.classes['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream);
    fstream.init(file, 1, 1, Components.interfaces.nsIFileInputStream.CLOSE_ON_EOF);
    var bstream = Components.classes['@mozilla.org/network/buffered-input-stream;1'].createInstance(Components.interfaces.nsIBufferedInputStream);
    bstream.init(fstream, 4096);
    var binary = Components.classes["@mozilla.org/binaryinputstream;1"].createInstance(Components.interfaces.nsIBinaryInputStream);
    binary.setInputStream(fstream);

    var data = "", size = 0;
    while ((size = binary.available()) > 0) {
        data += binary.readBytes(size);
    }
    return data;
}

var sendData = createMultipartData({
    status: "image upload from vimperator!",
    source: "vimperator/wassr.js",
    image: {
        filename: "example.jpg",
        contentType: "application/octet-stream",
        content: getFileContents("C:\\example.png")
    }
});

var req = new XMLHttpRequest();
req.open("POST", "http://api.wassr.jp/statuses/update.json");
req.setRequestHeader("Content-Type", sendData.contentType);
req.setRequestHeader("Content-Length", sendData.content.length);
req.sendAsBinary(sendData.content);
こんなんでどうでしょうか?
てかFirefox2の時、どうしてたの?苦笑
Posted at by