Microsoft Edge: SCRIPT0: SCRIPT0: 'FormData' is not defined - javascript

I have one XMLHttpRequest in javascript which is posting the FormData object to server. This call works fine in Chrome. On Microsoft Edge, I am seeing this error: "SCRIPT0: SCRIPT0: 'FormData' is not defined".
Here is my snippet:
function saveRecording(recordingData, endpoint, token) {
var randomNumber = Math.floor(100000 + Math.random() * 900000);
randomNumber = randomNumber.toString().slice(0, 4);
var recordingName = "Recording " + randomNumber;
var sender = {
sliceNumber: 1,
sliceMaxSize: 1024 * 1024,
sliceStart: 0,
sliceEnd: 1024 * 1024,
total: recordingData.blob.size,
recordlength: recordingData.length.toFixed(2),
fileName: '',
sendSlice: function () {
if (this.total > 0) {
var slice = undefined;
if (this.total >= this.sliceMaxSize) {
this.sliceEnd = this.sliceStart + this.sliceMaxSize;
}
else {
this.sliceEnd = this.sliceStart + this.total;
}
slice = recordingData.blob.slice(this.sliceStart, this.sliceEnd);
var isLastSlice = !((this.total - this.sliceMaxSize) > 0);
console.log(slice);
var formData = new FormData();
formData.append("data", slice);
formData.append("sliceMaxSize", this.sliceMaxSize);
formData.append("sliceNumber", this.sliceNumber);
formData.append("fileName", this.fileName);
formData.append("dictation", JSON.stringify(recordingData.dictation));
formData.append("isLastSlice", isLastSlice);
formData.append("length", this.recordlength);
formData.append("encoding", recordingData.encoding);
formData.append("name", recordingName);
//var params = 'data=ipsum&sliceMaxSize=binny&sliceMaxSize=binny&sliceMaxSize=binny&sliceMaxSize=binny&sliceMaxSize=binny&sliceMaxSize=binny';
var sender_this = this;
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
//readyState=4 means request finished and response is ready
if (this.readyState == 4) {
if (this.status == 200) {
//Success
sender_this.fileName = JSON.parse(this.response).fileName;
sender_this.sliceNumber++;
sender_this.sliceStart = sender_this.sliceStart + sender_this.sliceMaxSize;
sender_this.total = sender_this.total - sender_this.sliceMaxSize;
// send the next slice
sender_this.sendSlice();
}
else {
//Fail
self.postMessage({ command: "saveRecordingFail", message: JSON.parse(this.response) });
}
}
};
request.open("POST", endpoint, true);
request.setRequestHeader("Accept", "application/json, text/plain, */*");
//request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
request.setRequestHeader(token.name, token.value);
request.send(formData);
}
else {
//recording completely sent to server, post message to worker caller
self.postMessage({ command: "saveRecordingSuccess" });
}
}
};
// send the slice
sender.sendSlice();
}
Workaround already tried:
I have already checked that FormData works in edge by manually trying on the edge console which created the FormData object successfully.
FormData working fine in console of edge browser

I tried to make a test with sample code below and find that it is working fine with MS Edge browser (user agent string: IE 11)
<!doctype html>
<script>
let formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// List key/value pairs
for(let [name, value] of formData) {
alert(`${name} = ${value}`);
}
</script>
</html>
I suggest you to check all the values that you are trying to append and verify that all are having proper and correct values.
I suggest you to check all the values one by one to find the problematic value.
It may help to narrow down the issue. Than it will be easier for you to fix the issue.
Reference:
FormData

Related

JavaScript - file to bytes array

I'm trying to get a script to work, which is called sfo.js.
The repo mentions only this usage:
keys = parse_sfo(Some_ArrayBuffer);
console.log(keys['TITLE']);
Looking into the sfo.js, parse_sfo has the sfoBytes argument.
From this I've concluded the sfoBytes argument needs to be an arraybuffer of file bytes.
I've tried to make a script that parses the SFO file into a array of bytes:
<script src="sfo.js"></script>
<script>
function stringToArrayBuffer(str) {
var buf = [];
for (var i=0, strLen=str.length; i<strLen; i++) {
buf[i] = str.charCodeAt(i);
}
console.log(buf);
return buf;
}
function testing(url) {
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);
if (request.status === 200) {
console.log(request.response);
var response = request.response;
var array = stringToArrayBuffer(response);
return array;
} else {
alert('Error!');
}
}
var data = testing('param.sfo');
var sfo = parse_sfo(data);
</script>
That throws an error in the console:
Uncaught RangeError: byte length of Uint32Array should be a multiple of 4 at new Uint32Array (<anonymous>)
at readUint32At (sfo.js:20)
at parse_sfo (sfo.js:113)
at (index):29
I'm pretty sure I'm doing something wrong. Does anybody understand how I can make the script work properly?
I have a sample file for param.sfo: https://filebin.net/gghosrp6u93jn7y8 (if linking to a download is not allowed please let me know)
Ok, finally the working example.
I've found a small param.sfo file in the internet.
Notes:
there are 2 versions of file reader: local and remote
in the snippet below you can test both (I've added my param.sfo as an external link to test 'remote'). To test 'local' you just need to select any sfo file from you PC.
as a result I show all the keys, not only 'TITLE' (as it is in your question). You can then select desired key
function getSfoLocal(callback) {
// for now I use local file for testing
document.querySelector('input').addEventListener('change', function() {
var reader = new FileReader();
reader.onload = function() {
var arrayBuffer = this.result;
var array = new Uint8Array(arrayBuffer);
// var binaryString = String.fromCharCode.apply(null, array);
if (typeof callback === 'function') callback(array);
}
reader.readAsArrayBuffer(this.files[0]);
}, false);
}
function getSfoRemote(url, callback) {
var concatArrayBuffers = function(buffer1, buffer2) {
if (!buffer1) {
return buffer2;
} else if (!buffer2) {
return buffer1;
}
var tmp = new Uint8Array(buffer1.length + buffer2.length);
tmp.set(buffer1, 0);
tmp.set(buffer2, buffer1.byteLength);
return tmp.buffer;
};
fetch(url).then(res => {
const reader = res.body.getReader();
let charsReceived = 0;
let result = new Uint8Array;
reader.read().then(function processText({
done,
value
}) {
// Result objects contain two properties:
// done - true if the stream has already given you all its data.
// value - some data. Always undefined when done is true.
if (done) {
if (typeof callback === 'function') callback(result);
return result;
}
// value for fetch streams is a Uint8Array
charsReceived += value.length;
const chunk = value;
result = concatArrayBuffers(result, chunk);
// Read some more, and call this function again
return reader.read().then(processText);
});
});
}
function getSfo(type, url, callback) {
if (type === 'local') getSfoLocal(callback);
if (type === 'remote') getSfoRemote(url, callback);
}
getSfo('local', null, (data) => {
keys = parse_sfo(data);
console.log('LOCAL =', keys);
});
function goremote() {
getSfo('remote', 'https://srv-file9.gofile.io/download/Y0gVfw/PARAM.SFO', (data) => {
keys = parse_sfo(data);
console.log('REMOTE =', keys);
});
}
div { padding: 4px; }
<!--script src="https://rawcdn.githack.com/KuromeSan/sfo.js/c7aa8209785cc5a39c4231e683f6a2d1b1e91153/sfo.js" for="release"></script-->
<script src="https://raw.githack.com/KuromeSan/sfo.js/master/sfo.js" for="develop"></script>
<div>Local version: <input type="file" /></div>
<div>Remote version: <button onclick="goremote()">Go remote</button></div>
P.S. It seems that gofile.io service that I've used for remote example is not visible sometimes. If you have permanent link to param.sfo just let me know. But now I have to visit my file, and only after that it becomes visible.
You are using some 20 years old JavaScript.
Please use fetch add TextEncoder for your own sanity.
fetch(url).then(res => res.json().then(data => {
const encoder = new TextEncoder()
const bytes = encoder.encode(data)
parse_sfo(data)
})
sfoBytes should be the actual array buffer of the sfo file. It's simpler than what you are trying, you shouldn't need to convert the request response with stringToArrayBuffer since you can get an array buffer from XMLHttpRequest. Also, the SFO file isn't a text file, it's binary, so conversion from string wouldn't work anyway.
Changing your request to get a arraybuffer response type should do it like this:
function testing(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = "arraybuffer";
request.send(null);
if (request.status === 200) {
console.log(request.response);
var response = request.response;
var sfo = parse_sfo(response);
} else {
alert('Error!');
}
}

Dynamic PDF and opening a new window instead of downloading

I have a web api that is returning a JSReport as an encoded byte array. No matter how i try and read the byte array I either get a black screen or an error message that says "failed to download pdf". If I create a hidden anchor tag and download the pdf it works fine. However, I do not want the user to download it, I would prefer they can view it right from their browser.
WEB API CALL
var data = LossReportService.GetLossSummary(request);
var pdf_bytes = LossReportService.GeneratePDFUsingJSReport(data);
byte[] myBinary = new byte[pdf_bytes.Length];
pdf_bytes.Read(myBinary, 0, (int)pdf_bytes.Length);
string base64EncodedPDF = System.Convert.ToBase64String(myBinary);
var response = Request.CreateResponse(HttpStatusCode.OK, base64EncodedPDF);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = pdf_bytes.Length;
return response;
Javascript
$.ajax({
type: "POST",
url: "/Reporting/GetLossSummary",
data: { dataObj },
},
success: function (data) {
if (data != null) {
//I have tried this
var file = new Blob([data], { type: 'application/pdf;base64' });
var fileURL = URL.createObjectURL(file);
window.open(fileURL, "LossSummaryReport");
//which gives me a "failed to load pdf document" error
//and I have tried this, which just renders a blank page
window.open("data:application/pdf," + encodeURI(data));
}
}
});
Any suggestions would be greatly appreciated.
since you are using jsreport, in a normal case, you can use the jsreport browser sdk to better work with the report result and to easily show it in browser. but in your case, you are using a custom url in your server to render your report, so the jsreport browser sdk can't help you in that case. you need instead to work with the report request and response with either jQuery ajax or plain XMLHttpRequest.
working with blob/binary data is hard to do it with jQuery.ajax, you would need to add a data transport to $.ajax in order to handle binary data
/**
*
* jquery.binarytransport.js
*
* #description. jQuery ajax transport for making binary data type requests.
* #version 1.0
* #author Henry Algus <henryalgus#gmail.com>
*
*/
// use this transport for "binary" data type
$.ajaxTransport("+binary", function(options, originalOptions, jqXHR){
// check for conditions and support for blob / arraybuffer response type
if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
{
return {
// create new XMLHttpRequest
send: function(headers, callback){
// setup all variables
var xhr = new XMLHttpRequest(),
url = options.url,
type = options.type,
async = options.async || true,
// blob or arraybuffer. Default is blob
dataType = options.responseType || "blob",
data = options.data || null,
username = options.username || null,
password = options.password || null;
xhr.addEventListener('load', function(){
var data = {};
data[options.dataType] = xhr.response;
// make callback and send data
callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
});
xhr.open(type, url, async, username, password);
// setup custom headers
for (var i in headers ) {
xhr.setRequestHeader(i, headers[i] );
}
xhr.responseType = dataType;
xhr.send(data);
},
abort: function(){
jqXHR.abort();
}
};
}
});
but when handling blob data in an request/response i prefer doing it with XHTMLRequest directly because it let me manipulate the response in any way i want.
function sendReportRequest (dataObj, cb) {
var xhr = new XMLHttpRequest()
var data = JSON.stringify(dataObj)
xhr.open('POST', 'http://url-of-your-server/' + '/Reporting/GetLossSummary', true)
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8')
xhr.responseType = 'arraybuffer'
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
var response = xhr.response
var contentType = xhr.getResponseHeader('Content-Type')
var dataView = new DataView(response)
var blob
try {
blob = new Blob([dataView], { type: contentType })
cb(null, blob)
} catch (e) {
if (e.name === 'InvalidStateError') {
var byteArray = new Uint8Array(response)
blob = new Blob([byteArray.buffer], { type: contentType })
cb(null, blob)
} else {
cb(new Error('Can not parse buffer response'))
}
}
} else {
var error = new Error('request failed')
error.status = xhr.status
error.statusText = xhr.statusText
cb(error)
}
}
xhr.onerror = function () {
var error = new Error('request failed')
error.status = xhr.status
error.statusText = xhr.statusText
cb(error)
}
xhr.send(data)
}
sendReportRequest(dataObj, function (err, reportBlob) {
if (err) {
return console.error(err)
}
var reportFileUrl = URL.createObjectURL(reportBlob)
window.open(reportFileUrl)
})
with this piece of code you should be able to request a pdf file and show it right in the browser in a new window

Access response JSON array from XMLHttpRequest

I have a problem. I'm sending file via AJAX (XMLHttpRequest). Anyways. PHP function is returning a response array encoded to JSON. I can catch array in JavaScript but i can't access to specified key in array.
Here is the console log of this array:
{"data":"cos","data1":"cos1"}
I have my JavaScript file:
$('input[name=zdjecie]').on("change",function() {
var inputfile = document.querySelector('#file');
var file = inputfile.files[0];
$('button[type=submit]').addClass('disabled');
var formData = new FormData();
var request = new XMLHttpRequest();
request.upload.addEventListener('progress', function(e){
var pro = Math.round(e.loaded/e.total * 100);
if(pro == 100) {
$('#upload_progress').css({'width':pro+'%', background:'#00A65A'});
$('button[type=submit]').removeClass('disabled');
}
else {
$('#upload_progress').css({'width':pro+'%', background:'#3C8DBC'});
}
}, false);
formData.append('file', file);
request.open('post', '/admin/ajax/upload-admin-photo');
request.send(formData);
request.onloadend = function() {
var result = request.response;
console.log(result.data);
};
});
Now PHP function that is executing after POST request:
/**
* #Route("/admin/ajax/upload-admin-photo")
*/
public function ajaxUploadAdminPhotoAction(Request $request)
{
$data = $_FILES;
$response = array("data" => 'cos', 'data1' => 'cos1');
return new Response(json_encode($response));
}
Console log of variable result: {"data":"cos","data1":"cos1"}
Console log of variable result.data: undefined
I really need some help. I was trying everything! :(
You need to parse (=decode) the string '{"data":"cos","data1":"cos1"}' to a json first:
var result = JSON.parse(request.response);
// now you can access it's params:
console.log(result.data);
see the manual for more information.

XMLHttpRequest not working for IE 11 for file download

var formdata = new FormData();
var xhr = null;
if(typeof XMLHttpRequest != "undefined"){
xhr = new XMLHttpRequest();
}
else if(typeof window.ActiveXObject != "undefined"){
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP.4.0");
}
catch(e){
try {
xhr = new ActiveXObject("MSXML2.XMLHTTP");
}
catch(e){
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e){
xhr = null;
}
}
}
}
xhr.open("GET",url, true); ///fileUploadTester/FileUploader
xhr.send(formdata);
xhr.responseType = "arraybuffer";
xhr.onload = function(e) {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0) // If Internet Explorer, return version number
{
var urlIE = URL;
window.location = urlIE;
}
else
{
window.location = this.responseURL;
}
};
}
The above code is from my javaScript method when i call that method my requirement is to download file for user.
In java i have a method to generate file and add it to response
For other browsers i am able to call the method and get response back but for IE 11 i am not able to do.
Any Solution for this or any errors in my code?
Got the Answer The way i was getting browser name was wrong.
Once i got correct browser name using javascript it stated working
FormData() is not supported by ie11.u can build the formdata string by yourself.
function sendData(data) {
console.log('Sending data');
const XHR = new XMLHttpRequest();
const urlEncodedDataPairs = [];
// Turn the data object into an array of URL-encoded key/value pairs.
for (const [name, value] of Object.entries(data)) {
urlEncodedDataPairs.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);
}
// Combine the pairs into a single string and replace all %-encoded spaces to
// the '+' character; matches the behavior of browser form submissions.
const urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');
// Define what happens on successful data submission
XHR.addEventListener('load', (event) => {
alert('Yeah! Data sent and response loaded.');
});
// Define what happens in case of an error
XHR.addEventListener('error', (event) => {
alert('Oops! Something went wrong.');
});
// Set up our request
XHR.open('POST', 'https://example.com/cors.php');
// Add the required HTTP header for form data POST requests
XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// Finally, send our data.
XHR.send(urlEncodedData);
}
check this for more

POST request fails with no error message (Parse.com / ExpressJS)

I'm experiencing an issue where a POST request I make fails with error code 500 and nothing is printed in my server side error log. It's almost as if the cloud method doesn't exist for it.
What is strange though, is that the same POST request performs fine with smaller files. It starts to fail when the file gets to around 1.4 MB. I've tried changing the limit parameter of express.bodyParser like so "app.use(express.bodyParser( { limit: 10000000 } ));", however this makes no difference.
Here's some code:
function uploadFile(pageState)
{
var reader = new FileReader();
reader.onload = function()
{
var data = reader.result;
var byteArrayObj = new Uint8Array(data);
var byteArray = new Array(byteArrayObj.length);
for(i=0; i<byteArray.length; i++) {
byteArray[i] = byteArrayObj[i];
}
var json = { data: byteArray };
var jsonString = JSON.stringify(json);
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "/assetUploader/"+pageState.assetIdentifier+"/"+pageState.fileName+"/"+pageState.isAssetBundle+"/"+pageState.uploadToProduction, true);
xmlhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.onload = function(evt) {
...
};
xmlhttp.send(jsonString);
};
reader.readAsArrayBuffer( pageState.fileRef );
}
On the cloud side:
app.post('/assetUploader/:fileIdentifier/:fileName/:isAssetBundle/:useProd', function(req, res)
{
console.log("assetUpload Post");
var fileId = req.params.fileIdentifier;
var fileName = req.params.fileName;
var assetBundle = req.params.isAssetBundle == "true";
var bytes = req.body.data;
var useProd = req.params.useProd == "true";
createParseFile(fileName, bytes, useProd).then( function(response) {
return currentVersionForAsset(fileId, useProd).then(function(versionNumber) {
return {
"fileIdentifier": fileId,
"file": {
"name": response.data.name,
"__type": "File"
},
"isAssetBundle": assetBundle,
"fileVersion": versionNumber+1
};
});
}).then(function(json) {
return createParseObject("DownloadableAsset", json, useProd);
}).then( function() {
res.send(200);
}, function(error) {
res.send(400, error.message);
});
});
Any help or suggestions would be much appreciated. Thanks for your time!
i suggest using res.setTimeout with a very large number of milisecs. perhaps your response simply times out, and from my experience node doesn't throw an error when it happens.

Categories