XMLHttpRequest模拟表单上传文件
用XMLHttpRequest以Post方式发送一些表单请求啦,没什么问题。
但是如果表单里面有文件域呢?对这种情况,POST出去的数据不能进行额外编码,否则服务器那边不认识。
看上去w3c没有为XMLHttpRequest发送二进制数据提供支持。不信你可以直接
编造一个含有’\0′的binary_data,然后
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.send(binary_data);
看看是什么情况。
好吧,我承认这个需求基本上没有什么意义。因为
- XMLHttpRequest被浏览器限制默认无法跨域。
- 本域的话用XMLHttpRequest模拟表单上传文件会被人认为是BTer
但是我说Firefox插件Firefox扩展需要。
尽管M$和Mozilla都提供了解决方案:M$的Adobe.stream,Mozilla的XPCOM binary-stream。但是显然,只有Mozilla适合我,否则就是不坚贞,玩着家里的看着外面的,显然,我是好Boy,我知道外面的不干净。
XPCOM,不是XP上的COM,也不是基于XP的发行版,是Mozilla在Netscape的基础上捣鼓出来的一套OOXX。
虽然Gecko被人骂,但是没有这个引擎提供的那一堆零碎,你的Firefox根本玩不转。所以还是感谢一下Mozilla那帮牛B人。
跑题了。
模拟表单发送文件域的关键在于,让XMLHttpRequest能发送2进制串;而发送2进制串的关键呢,nsIBinaryInputStream。
代码比较Ugly,意思意思,别在意。
function upload(file) {
const MULTI = "@mozilla.org/io/multiplex-input-stream;1";
const STRINGIS = "@mozilla.org/io/string-input-stream;1";
const BINIS = "@mozilla.org/io/binaryinputstream;1";
const BOUNDARY = "-----------------------------19842867121279461543193888023";
var xhr;
var url = "http://127.0.0.1/upload.php"
function infoReceived() {
var output = xhr.responseText;
alert(output);
}
// binary stream
var fstream =
Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
fstream.init(file, -1, -1, false);
var data_body_stream =
Components.classes["@mozilla.org/binaryinputstream;1"]
.createInstance(Components.interfaces.nsIBinaryInputStream);
data_body_stream.setInputStream(fstream);
// first boundary and field header
var data_header = BOUNDARY + '\r\n'
+ 'Content-Disposition: form-data; name="photo1"; filename="'
+ file_name + '"\r\n'
+ 'Content-Type: image/png\r\n\r\n';
var data_header_stream = Components.classes[STRINGIS]
.createInstance(Components.interfaces.nsIStringInputStream);
data_header_stream.setData(data_header, data_header.length);
// last boundary
var data_tail = '\r\n' + BOUNDARY + '--\r\n';
var data_tail_stream = Components.classes[STRINGIS]
.createInstance(Components.interfaces.nsIStringInputStream);
data_tail_stream.setData(data_tail, data_tail.length);
// mix multi-stream
var mux_stream = Components.classes[MULTI]
.createInstance(Components.interfaces.nsIMultiplexInputStream);
mux_stream.appendStream(data_header_stream);
mux_stream.appendStream(data_body_stream);
mux_stream.appendStream(data_tail_stream);
// post
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + BOUNDARY);
xhr.setRequestHeader("Content-Length", mux_stream.available() );
xhr.onload = infoReceived;
xhr.send(mux_stream);
}
嗯。这个代码着色插件真是好哦。
FireFox 跨域可以用 js 语句
netscape.security.PrivilegeManager.enablePrivilege(“UniversalBrowserRead”);
请求,
页面会弹出对话框询问用户是否允许