XMLHttpRequest POST formData to a new tab [duplicate] - javascript

This question already has an answer here:
How to pass formData to postData in loadOneTab?
(1 answer)
Closed 8 years ago.
Since, loadOneTab() is not available for formData,
How can formData be posted to a new tab?
How can the above new tab foreground/background status be set?
Just a smaple example from Using FormData Objects:
var formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456); // number 123456 is immediately converted to string "123456"
// HTML file input user's choice...
formData.append("userfile", fileInputElement.files[0]);
// JavaScript file-like object...
var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var blob = new Blob([content], { type: "text/xml"});
formData.append("webmasterfile", blob);
var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);
Clarification:
Normal HTML form with a target="_blank" will POST the form data to a new tab.
Similarly, as mentioned, loadOneTab() can also POST data to a new tab.
Is it possible to do so with XMLHttpRequest?

XHR has absolutely nothing to do with tabs. If you really want to XHR it, then you should take the returned source and update document of the target tab with it.
Otherwise I would just use loadOneTab:
I would think something like this where things are turned into nsIFile:
Import encodeFormData function form here: https://stackoverflow.com/a/25020668/3791822
// HTML file input user's choice...
var userfileNSIFILE = new FileUtils.File(fileInputElement.files[0].path);
// JavaScript file-like object...
var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var blob = new Blob([content], { type: "text/xml"});
//some code here to write blob to temp folder to make nsifile or do some stream stuff to get an nisfileoutputstream?
var blobNSIFILE = ....;
let postData = encodeFormData({
"webmasterfile": blobNSIFILE,
"userfile": userfileNSIFILE,
"username": "Groucho",
"accountnum": 123456
}, "iso8859-1");
gBrowser.loadOneTab("http://foo.com/submitform.php", {
inBackground: false,
postData: postData
});

This is what I mean by loading responseText of xhr into a tab, can copy paste to scratchpad.
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
switch (xhr.readyState) {
case 4:
prompt('done', xhr.responseText);
gBrowser.loadOneTab('data:text/html, ' + encodeURIComponent(xhr.responseText), {
inBackground: false
});
break;
default:
}
};
xhr.open("GET", "https://www.bing.com/");
xhr.send();

Related

No file was sent to SAP Leonardo Image Feature Extraction API using FormData

I'm testing SAP Leonardo Image Feature Extraction API (https://sandbox.api.sap.com/ml/featureextraction/inference_sync). I have the base64 string of the image and I want to transform it to a file object and zip it, then to send the zipped image file to this API using XMLHttpRequest. But the response text is "Service requires a list of (zipped) images".
I attach my HTTP request header and parameters in below screenshots.
Although we see a messy code in parameters, the zipped file Download here is created successfully.
If you cannot download the zipped file, please refer to the screenshot below.
Everything seems to be fine. However, the response text is as below with status 400.
My javascript code is shown below. What is wrong? It drives me crazy...
dataURItoBlob: function(dataURI, fileName) {
//convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
//separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
//write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
var blob = new Blob([ia], {encoding:"UTF-8",type:mimeString});
//A Blob() is almost a File() - it's just missing the two properties below which we will add
blob.lastModifiedDate = new Date();
blob.name = fileName + '.' + mimeString.split('/')[1];
return blob;
},
onSubmit: function(oEvent) {
var oImage = this.getView().byId('myImage');
//oImage.getSrc() : 'data:image/png;base64,iVBORw0KGgo...'
var imageFile = this.dataURItoBlob(oImage.getSrc(), 'myImage');
var zip = new JSZip();
zip.file(imageFile.name, imageFile);
zip.generateAsync({
type:"blob",
compression: 'DEFLATE', // force a compression for this file
compressionOptions: {
level: 6,
},
}).then(function(content) {
//saveAs(content, "hello.zip");
// start the busy indicator
var oBusyIndicator = new sap.m.BusyDialog();
oBusyIndicator.open();
var formData = new FormData();
formData.append('files', content, 'myImage.zip');
var xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
oBusyIndicator.close();
//navigator.notification.alert(this.responseText);
console.log(this.responseText);
}
});
//setting request method
//API endpoint for API sandbox
//Destionation '/SANDBOX_API' in HCP is configured as 'https://sandbox.api.sap.com'
var api = "/SANDBOX_API/ml/featureextraction/inference_sync";
xhr.open("POST", api);
//adding request headers
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("Accept", "application/json");
//API Key for API Sandbox
xhr.setRequestHeader("APIKey", "yQd5Oy785NkAIob6g1eNwctBg4m1LGQS");
//sending request
xhr.send(formData);
});
},
I fix this issue by myself. I put my solution just for others' information. It's very easy and only below code needs to be removed before sending request. I have no idea why. Please suggest if you know the reason. Thanks in advance!
xhr.setRequestHeader("Content-Type", "multipart/form-data");
Best Regards,
Shelwin Wei

how to instantiate new file object javascript

I'm having troubles instantiating a new file object in javascript.
Here's the general gist of what I'm trying to do. There is client side code that expecting a "file" type object. I need to access the file that's located on the server (game.smc), download it to the local machine and feed it to the client side code.
I did some research and found that creating a new blob object is the first step. But in the code below the blob object remains null and is never getting populated. Does the path in the xhr.open need to have the entire url? Maybe i'm missing an entire concept here not sure.
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", "/Roms/game.smc");
xhr.responseType = "blob";
xhr.onload = function()
{
blob = xhr.response;
}
xhr.send();
Once I can get the blob object populated I can then do this to convert it to a file object.
function blobToFile(theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
This is what I ended up doing. Shows how to get the blob object as well as convert it to a file type.
function autoLoadGame(fileName) {
var gameLocation = '/Content/Roms/Snes/' + fileName;
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", gameLocation, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
var blob = xhr.response;
var file = new File([blob], fileName, { type: '', lastModified: Date.now() });
snes_readfile(file);
}
}
xhr.responseType = "blob";
xhr.send();
}

InboxSDK - Unable to attachFiles through composeView object

I am trying to attach an attachment through the composeView object using Inboxsdk. I obtain a blob object from a remote url using the following code.
// FUNCTION TO OPEN A NEW COMPOSE BOX ONCE THE ATTACHMENT BLOB IS OBTAINED FROM REMOTE URL.
function openComposeBox(sdk, blob){
handler = sdk.Compose.registerComposeViewHandler(function(composeView){
if(blob != null){
composeView.attachFiles([blob]);
composeView.setSubject("Testing");
}
});
}
// FETCHING ATTACHMENT FILE FROM REMOTE URL
var file_btn_url = "https://api.hummingbill.com/system/invoices/invoice_files/000/033/393/original/abracadabra.txt";
var file_name = file_btn_url.split("/");
file_name = file_name[file_name.length-1];
file_type = /[^.]+$/.exec(file_name);
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", file_btn_url);
xhr.responseType = "blob";
xhr.onload = function()
{
blob = xhr.response;
// blob.lastModifiedDate = new Date(); // Since it's not necessary to have it assigned, hence commented.
blob.name = file_name;
console.log(blob);
openComposeBox(sdk, blob);
}
xhr.send();
It shows an Attachment Failed error.
Although I have the correct format of blob object as required as per the documentation.
As per the documentation, I have set the filename for the blob, and passed it in an array to attachFiles function. Can you please look into it and let me know what am I missing?
Posting the solution. The code remains same as in the question, with a slight variation, wherein we convert the blob to a file, in order to make it work.
//... Same as the code in the question
// Fetching attachment file from remote url
var file_btn_url = "https://api.hummingbill.com/system/invoices/invoice_files/000/033/393/original/abracadabra.txt";
var file_name = file_btn_url.split("/");
file_name = file_name[file_name.length-1];
file_type = /[^.]+$/.exec(file_name);
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", file_btn_url);
xhr.responseType = "blob";
xhr.onload = function()
{
// Solution: Convert the obtained blob to a file
// Pass the file to openComposeBox
blob = new Blob([xhr.response], { type: xhr.responseType });
var file = new File([blob], file_name);
blob.name = file_name;
openComposeBox(sdk, file);
}
xhr.send();
Hope this helps. Cheers!

Pass parameter to BLOB object URL

Say I've got a reference to a html file as a Blob b and I create a URL for it, url = URL.createObjectURL(b);.
This gives me something that looks like blob:http%3A//example.com/a0440b61-4850-4568-b6d1-329bae4a3276
I then tried opening this in an <iframe> with a GET parameter ?foo=bar, but it didn't work. How can I pass the parameter?
var html ='<html><head><title>Foo</title></head><body><script>document.body.textContent = window.location.search<\/script></body></html>',
b = new Blob([html], {type: 'text/html'}),
url = URL.createObjectURL(b),
ifrm = document.createElement('iframe');
ifrm.src = url + '?foo=bar';
document.body.appendChild(ifrm);
// expect to see ?foo=bar in <iframe>
DEMO
I don't think adding a query string to the url will work as it essentially changes it to a different url.
However if you simply want to pass parameters you can use the hash to add a fragment to the url
ifrm.src = url + '#foo=bar';
http://jsfiddle.net/thpf584n/1/
For completeness sake, if you want to be able to reference a blob that has as question mark "query string" indicator in it, you can do so in Firefox any way you choose, such as: blob:lalalal?thisworksinfirefox
For Chrome, the above will not work, but this will: blob:lalalla#?thisworksinchromeandfirefox
And for Safari and Microsaft, nothing really works, so do a pre test like so, then plan accordingly:
function initScriptMode() {
var file = new Blob(["test"], {type: "text/javascript"});
var url = URL.createObjectURL(file) + "#test?test";
var request = new XMLHttpRequest();
request.responseType = responseType || "text";
request.open('GET', url);
request.onload = function() {
alert("you can use query strings")
};
try {
request.send();
}
catch(e) {
alert("you can not use query strings")
}
}
If you are doing this with a Javascript Blob for say a WebWorker then you can just to add the parameters into the Blob constructor as a global variable:
const parameters = 'parameters = ' + JSON.stringify({foo:'bar'});
const body = response.body; // From some previous HTTP request
const blob = new Blob([parameters, body], { type: 'application/javascript' });
new Worker(URL.createObjectURL(blob));
Or more general case just store the original URL on the location object
const location = 'location.originalHref = "' + url + '";';
const body = response.body; // From some previous HTTP request
const blob = new Blob([location, body], { type: 'application/javascript' });
new Worker(URL.createObjectURL(blob));
You could also do this with HTML if you can add them say to the root <HTML> tag as attributes or use the <BASE> element for the url or insert them as a script tag but this would require you to modify the response HTML rather then just prepend some extra data

Use Blob on firefox add-on

Been trying to get the following code to work in firefox add-on:
var oMyForm = new FormData();
oMyForm.append("username", "Groucho");
oMyForm.append("accountnum", 123456); // number 123456 is immediately converted to string "123456"
// HTML file input user's choice...
oMyForm.append("userfile", fileInputElement.files[0]);
// JavaScript file-like object...
var oFileBody = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var oBlob = new Blob([oFileBody], { type: "text/xml"});
oMyForm.append("webmasterfile", oBlob);
var oReq = new XMLHttpRequest();
oReq.open("POST", "http://foo.com/submitform.php");
oReq.send(oMyForm);
from https://developer.mozilla.org/en-US/docs/Web/Guide/Using_FormData_Objects?redirectlocale=en-US&redirectslug=Web%2FAPI%2FFormData%2FUsing_FormData_Objects
So I know I have to use XPCOM, but I can't find the equivalent. I found this so far:
var oMyForm = Cc["#mozilla.org/files/formdata;1"].createInstance(Ci.nsIDOMFormData);
oMyForm.append("username", "Groucho");
oMyForm.append("accountnum", 123456); // number 123456 is immediately converted to string "123456"
// JavaScript file-like object...
var oFileBody = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var oBlob = Cc["#mozilla.org/files/file;1"].createInstance(Ci.nsIDOMFile, [oFileBody], { type: "text/xml"});
oMyForm.append("webmasterfile", oBlob);
var oReq = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
oReq.open("POST", "http://localhost:3000");
oReq.send(oMyForm);
Essentially the problem is var oBlob = Cc["#mozilla.org/files/file;1"].createInstance(Ci.nsIDOMFile, [oFileBody], { type: "text/xml"}); because "#mozilla.org/files/file;1" or Ci.nsIDOMFile is incorrect. Note that nsIDOMFile is inherits from nsIDOMBlob.
Anyone know what to do?
Thanks a bunch.
Let's cheat a little to answer this:
JS Code Modules actually have Blob and File, while SDK modules do not :(
Cu.import() will return the full global of a code module, incl. Blob.
Knowing that, we can just get a valid Blob by importing a known module, such as Services.jsm
Complete, tested example, based on your code:
const {Cc, Ci, Cu} = require("chrome");
// This is the cheat ;)
const {Blob, File} = Cu.import("resource://gre/modules/Services.jsm", {});
var oMyForm = Cc["#mozilla.org/files/formdata;1"].createInstance(Ci.nsIDOMFormData);
oMyForm.append("username", "Groucho");
oMyForm.append("accountnum", 123456); // number 123456 is immediately converted to string "123456"
// JavaScript file-like object...
var oFileBody = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var oBlob = Blob([oFileBody], { type: "text/xml"});
oMyForm.append("webmasterfile", oBlob, "myfile.html");
var oReq = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
oReq.open("POST", "http://example.org/");
oReq.send(oMyForm);

Categories

Resources