Репликация метода Form с помощью loadOneTab
Если я динамически вставляю объект формы на страницу, отправляю и удаляю форму, и она работает нормально.
Вот пример кода формы:
<form target="_blank" enctype="multipart/form-data"
action="https://www.example.com/" method="POST">
<input value="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" name="image_content" type="hidden">
<input value="" name="filename" type="hidden">
<input value="" name="image_url" type="hidden">
</form>
Когда я пытаюсь сделать тот же процесс с loadOneTab()
результат POST
не совсем то же самое, и, следовательно, результат не такой, как указано выше.
При проверке заголовков "некоторое значение" отправляется не полностью (обрезается) и устанавливает Content-Length: 0
,
Я должен что-то упустить.
let postStream = Components.classes['@mozilla.org/network/mime-input-stream;1']
.createInstance(Components.interfaces.nsIMIMEInputStream);
postStream.addHeader('Content-Type', 'multipart/form-data');
postStream.addHeader('filename', '');
postStream.addHeader('image_url', '');
postStream.addHeader('image_content', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==');
postStream.addContentLength = true;
window.gBrowser.loadOneTab('https://www.example.com/',
{inBackground: false, postData: postStream});
Примечание: значение image_content равно 'data:image/png;base64' URI данных
NoScript вызывает проблемы с отправкой формы и XSS, и я предпочитаю использовать loadOneTab
для inBackground
1 ответ
Обычно можно использовать FormData
составить postData
запроса, но, к сожалению, мы не можем сделать это здесь, так как в настоящее время нет способа получить поток (и другую информацию) из FormData
пример (nsIXHRSendable
к сожалению, это не сценарий), поэтому нам придется создать multipart/form-data
Поток себя.
Поскольку вы, вероятно, захотите также опубликовать некоторые данные файла, я также добавил загрузку файлов.;)
function encodeFormData(data, charset) {
let encoder = Cc["@mozilla.org/intl/saveascharset;1"].
createInstance(Ci.nsISaveAsCharset);
encoder.Init(charset || "utf-8",
Ci.nsISaveAsCharset.attr_EntityAfterCharsetConv +
Ci.nsISaveAsCharset.attr_FallbackDecimalNCR,
0);
let encode = function(val, header) {
val = encoder.Convert(val);
if (header) {
val = val.replace(/\r\n/g, " ").replace(/"/g, "\\\"");
}
return val;
}
let boundary = "----boundary--" + Date.now();
let mpis = Cc['@mozilla.org/io/multiplex-input-stream;1'].
createInstance(Ci.nsIMultiplexInputStream);
let item = "";
for (let k of Object.keys(data)) {
item += "--" + boundary + "\r\n";
let v = data[k];
if (v instanceof Ci.nsIFile) {
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
fstream.init(v, -1, -1, Ci.nsIFileInputStream.DEFER_OPEN);
item += "Content-Disposition: form-data; name=\"" + encode(k, true) + "\";" +
" filename=\"" + encode(v.leafName, true) + "\"\r\n";
let ctype = "application/octet-stream";
try {
let mime = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
ctype = mime.getTypeFromFile(v) || ctype;
}
catch (ex) {
console.warn("failed to get type", ex);
}
item += "Content-Type: " + ctype + "\r\n\r\n";
let ss = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
ss.data = item;
mpis.appendStream(ss);
mpis.appendStream(fstream);
item = "";
}
else {
item += "Content-Disposition: form-data; name=\"" + encode(k, true) + "\"\r\n\r\n";
item += encode(v);
}
item += "\r\n";
}
item += "--" + boundary + "--\r\n";
let ss = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
ss.data = item;
mpis.appendStream(ss);
let postStream = Cc["@mozilla.org/network/mime-input-stream;1"].
createInstance(Ci.nsIMIMEInputStream);
postStream.addHeader("Content-Type",
"multipart/form-data; boundary=" + boundary);
postStream.setData(mpis);
postStream.addContentLength = true;
return postStream;
}
(Вы можете использовать дополнительные nsIMIMEInputStream
вместо того, чтобы объединять строки вместе, но это будет работать хуже и не будет иметь реальных достоинств).
Который затем можно использовать как, например:
let file = Services.dirsvc.get("Desk", Ci.nsIFile);
file.append("australis-xp hällow, wörld.png");
let postData = encodeFormData({
"filename": "",
"image_url": "",
"image_content": "--somne value ---",
"contents": file
}, "iso8859-1");
gBrowser.loadOneTab("http://www.example.org/", {
inBackground: false,
postData: postData
});