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(
Parameters
in DOMString body
);
body
https://developer.mozilla.org/en/XMLHttpRequest#sendAsBinary%28%29The 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).
見事送信する事が出来ました。
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の時、どうしてたの?苦笑