I would like to send some data to an external server within an Firefox extension.
I tried this code snippet but it doesn’t work, due to Same-Origin-Policy.
$.ajax({
type: "POST",
url: 'https://127.0.0.1:54321',
data: ({foo: "bar"}),
crossDomain: true,
dataType: 'json'
}).done(function () {
alert("done");
}).fail(function(xhr, status, error) {
// var err = eval("(" + xhr.responseText + ")");
alert((xhr.responseText));
});
Since this does not work, I tried this tutorial:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
That got me this piece of code:
var invocation = new XMLHttpRequest(); var url = 'https://127.0.0.1:54321';
invocation.open('POST', url, true);
invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
invocation.setRequestHeader('Content-Type', 'application/xml');
invocation.onreadystatechange = handler;
invocation.send(document.body);
This code also doesn't work and Firefox prompts that I should use CORS.
The weird thing is that it works if I don't use HTTPS (on non-HTTPS sites).
Note: On https://127.0.0.1:54321 runs a Java SSLServerSocket.
Copy paste this:
var {Cu, Cc, Ci} = require('chrome'); //addon-sdk way
//var {Cu: utils, Cc: classes, Ci: instances} = Components; //non addon-sdk
Cu.import('resource://gre/modules/Services.jsm');
function xhr(url, cb) {
let xhr = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
let handler = ev => {
evf(m => xhr.removeEventListener(m, handler, !1));
switch (ev.type) {
case 'load':
if (xhr.status == 200) {
cb(xhr.response);
break;
}
default:
Services.prompt.alert(null, 'XHR Error', 'Error Fetching Package: ' + xhr.statusText + ' [' + ev.type + ':' + xhr.status + ']');
break;
}
};
let evf = f => ['load', 'error', 'abort'].forEach(f);
evf(m => xhr.addEventListener(m, handler, false));
xhr.mozBackgroundRequest = true;
xhr.open('GET', url, true);
xhr.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS | Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_PERSISTENT_CACHING;
//xhr.responseType = "arraybuffer"; //dont set it, so it returns string, you dont want arraybuffer. you only want this if your url is to a zip file or some file you want to download and make a nsIArrayBufferInputStream out of it or something
xhr.send(null);
}
xhr('https://www.gravatar.com/avatar/eb9895ade1bd6627e054429d1e18b576?s=24&d=identicon&r=PG&f=1', data => {
Services.prompt.alert(null, 'XHR Success', data);
var file = OS.Path.join(OS.Constants.Path.desktopDir, "test.png");
var promised = OS.File.writeAtomic(file, data);
promised.then(
function() {
alert('succesfully saved image to desktop')
},
function(ex) {
alert('FAILED in saving image to desktop')
}
);
});
Related
In ionic 2, I'm using below code to upload the file(.pdf and .doc extension) into server via API. But I'm not able to call any function after resp.success == 1 or not able to use any global variables.I'm getting error like property doesn't exist on type xmlhttpeventtarget As I want to navigate user to next page on successful submission of the file I need call some function inside success.
xhr.open('POST', "myurl", true);
xhr.onload = function() {
if (xhr.status == 200) {
var resp = JSON.parse(xhr.response);
console.log('Server got: in IOS ', resp);
console.log('Server got: in IOS ', resp.message);
if(resp.success == 1)
{
console.log("THIS IS SUCCESS")
}
else{
alert(resp.message)
return
}
};
}
xhr.send(this.fd);
A better way to solve this would be by using arrow functions like this:
xhr.open('POST', "myurl", true);
xhr.onload = () => {
if (xhr.status == 200) {
var resp = JSON.parse(xhr.response);
console.log('Server got: in IOS ', resp);
console.log('Server got: in IOS ', resp.message);
if(resp.success == 1) {
console.log("THIS IS SUCCESS");
// Now 'this' points to the component :) !!
this.yourcustomfunction();
this.yourvariableblename;
} else{
alert(resp.message)
return
}
};
}
xhr.send(this.fd);
Notice that now we do
xhr.onload = () => {...});
instead of
xhr.onload = function() {...});
By using arrow functions, the this property is not overwritten and still references the component instance (otherwise, the this keyword points to the inner function, and your custom method and variable are not defined in it).
Hi I found solution to this problem.By creating a variable which has this reference, the snippet is as below.
var self = this;
xhr.open('POST', "myurl", true);
xhr.onload = function() {
if (xhr.status == 200) {
var resp = JSON.parse(xhr.response);
console.log('Server got: in IOS ', resp);
console.log('Server got: in IOS ', resp.message);
if(resp.success == 1)
{
console.log("THIS IS SUCCESS")
self.yourcustomfunction()
self.yourvariableblename
}
else{
alert(resp.message)
return
}
};
}
xhr.send(this.fd);
I am using AJAX to download the excel file from server. But the downloaded data is different from actual data
Actual data is with orange background. Received data is in yellow background.
From the difference file, it looks like they are using different encoding formats. So excel throws error that the file is not in correct format.
$.ajax({
url: exporting.action,
headers: { "Authorization": "Basic " + btoa("key : " + key) },
type: "post",
responseType: "arraybuffer",
success: function (res, status, obj) {
var blob = new Blob([str2ab(res)], { type: obj.getResponseHeader('Content-Type') });
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
},
data: { 'Model': JSON.stringify(modelClone) }
});
Please help to resolve this
The trouble with "encoding" is caused that jQuery did not response arraybuffer but string. Strings are in JavaScript UTF-16 and binary data in string cause trouble next to trouble. I recommend you to use native AJAX instead of jQuery. Code is similar and browser support is the same as the browser support of blobs and object URLS what you use.
var xhr = new XMLHttpRequest();
xhr.open("POST", exporting.action);
xhr.setRequestHeader("Authorization", "Basic " + btoa("key : " + key));
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var blob = new Blob([xhr.response], { type: xhr.getResponseHeader('Content-Type') });
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}
}.bind(this);
xhr.send({ 'Model': JSON.stringify(modelClone)});
I am trying to upload an image to cloudinary using ionic cordova plugin. I can successfully post my image to cloudinary, but the response i received in xcode shows [object Object]. I would like to get the details of the response.
I tried printing the result using different ways such as iterating the keys of object, and nothing is been printed. is there a way for xcode to print out ionic console.log response? My code is as follow:
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope, $cordovaCamera, $cordovaGeolocation, $cordovaFileTransfer, $q, $base64, $translate) {
//$scope.$inject = ['$cordovaCamera','$cordovaGeolocation','$cordovaFileTransfer'];
$scope.imageURI = '';
$scope.log=function(){
console.log('hello~~~');
};
$scope.takePicture = function() {
console.log('taking pictures ....');
var uploadOptions = {
params : { 'upload_preset': "MY_PRESET"}
};
var options = {
quality: 50,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
encodingType: Camera.EncodingType.JPEG,
};
$cordovaCamera.getPicture(options).then(function(imageData) {
$scope.imageURI = imageData;
var ft = new FileTransfer();
function win (){
console.log('upload successful');
}
function fail(){
console.log('upload fail');
}
return $cordovaFileTransfer.upload("https://api.cloudinary.com/v1_1/MY_DOMAIN/image/upload", $scope.imageURI, uploadOptions);
})
.then(function(result){
console.log('result is~~~~~~ ', result);
console.log('print the result object '); // this shows nothing
var test1=JSON.parse(decodeURIComponent(result.response);
var test2=JSON.parse(decodeURIComponent(result);
console.log('test1 is ', test1); // didn't even print!!
console.log('test2 is ', test2); // didn't even print!!
for(var property in result[0]) {
console.log(property + "=" + obj[property]); // nothing here
}
for(var property in result[1]) {
console.log(property + "=" + obj[property]);// nothing here
}
for(var property in result) {
console.log(property + "=" + obj[property]);// nothing here
}
var url = result.secure_url || '';
var urlSmall;
if(result && result.eager[0]) { // this is not working
urlSmall = result.eager[0].secure_url || '';
console.log('url ~~~~~~~~ is ', urlSmall);
chat.sendMessage(roomId,'', 'default', urlSmall, function(result){
console.log('url is ', urlSmall);
console.log('message image url successfully updated to firebase');
})
}
// Do something with the results here.
$cordovaCamera.cleanup();
}, function(err){
// Do something with the error here
console.log('something is erroring')
$cordovaCamera.cleanup();
});
};
})
i have some issues with onload image and angular-fie-upload. first, i have to validate an image size after that i will upload this image to server side with the following code. my service look like that :
Services.factory('$uploadWrapper', ['$upload' , '$logger' , function ($upload, $logger) {
return function (url, file, informations, onSuccess, onError, onProgress) {
url = url || angular.noop;
file = file || angular.noop;
informations = informations || angular.noop;
onSuccess = onSuccess || angular.noop;
onError = onError || angular.noop;
onProgress = onProgress || angular.noop;
$upload.upload({
url: url,
method: 'POST',
// headers: {'header-key': 'header-value'},
// withCredentials: true,
data: informations,
file: file // or list of files: $files for html5 only
/* set the file formData name ('Content-Desposition'). Default is 'file' */
//fileFormDataName: myFile, //or a list of names for multiple files (html5).
/* customize how data is added to formData. See #40#issuecomment-28612000 for sample code */
//formDataAppender: function(formData, key, val){}
}).progress(function (evt) {
$logger.info(Math.min(100, parseInt(100.0 * evt.loaded / evt.total)));
onProgress(evt);
}).success(function (response) {
$logger.info('POST' + url + angular.toJson(response))
onSuccess(response);
}).error(function (error) {
$logger.error('POST' + url + ' ' + angular.toJson(error));
onError(error);
});
}
}]);
and for validation process, i will create an image to take the width and the height of my image :
$scope.onFileSelect = function ($files) {
$scope.loading = true;
//$files: an array of files selected, each file has name, size, and type.
file = $files[0];
var img = new Image();
img.src = _URL.createObjectURL(file);
img.onload = function () {
console.log(this.width + "x" + this.height);
if (img.width > sizes.width && img.height > sizes.height) {
$uploadWrapper(pinholeAdminServerRoutes.image.upload, file, {
"operationType": 'channels',
"objectId": $scope.channel.id,
"size": 'large'
}, function (response) {
$scope.loading = false;
}, function (error) {
$scope.errors.push(error);
$scope.loading = false;
});
} else {
$scope.imageSizeNotValid = true;
$scope.loading = false;
}
console.log('finish loading');
};
};
but, my service won't work inside the onload block. but the same service will work without the onload block.
i finally got a solution by using $scope.$apply inside the onload event.
I have a HTML form for filling the personal profile, which includes String and Images. And I need to post all these data as JsonObject with one backend api call, and the backend requires the image file sent as binary data. Here is my Json Data as follow:
var profile = {
"userId" : email_Id,
"profile.name" : "TML David",
"profile.profilePicture" : profilePhotoData,
"profile.galleryImageOne" : profileGalleryImage1Data,
"profile.referenceQuote" : "Reference Quote"
};
and, profilePhotoData, profileGalleryImage1Data, profileGalleryImage2Data, profileGalleryImage3Data are all image Binary data(Base64).
And here is my post function:
function APICallCreateProfile(profile){
var requestUrl = BASE_URL + API_URL_CREAT_PROFILE;
$.ajax({
url: requestUrl,
type: 'POST',
data: profile,
dataType:DATA_TYPE,
contentType: CONTENT_TYPE_MEDIA,
cache:false,
processData:false,
timeabout:API_CALL_TIMEOUTS,
success: function (response) {
console.log("response " + JSON.stringify(response));
var success = response.success;
var objectData = response.data;
if(success){
alert('CreateProfile Success!\n' + JSON.stringify(objectData));
}else{
alert('CreateProfile Faild!\n'+ data.text);
}
},
error: function(data){
console.log( "error" +JSON.stringify(data));
},
failure:APIDefaultErrorHandler
})
.done(function() { console.log( "second success" ); })
.always(function() { console.log( "complete" ); });
return false;
}
But still got failed, I checked the server side, and it complains about the "no multipart boundary was found".
Can anyone help me with this, thanks:)
Updates:
var DATA_TYPE = "json";
var CONTENT_TYPE_MEDIA = "multipart/form-data";
I think I found the solution with vineet help. I am using XMLHttpRequest, and didn't set the requestHeader, but it works, very strange. But hope this following can help
function APICallCreateProfile(formData){
var requestUrl = BASE_URL + API_URL_CREAT_PROFILE;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function()
{
if (xhr.readyState==4 && xhr.status==200){
console.log( "profile:" + xhr.responseText);
}else if (xhr.readyState==500){
console.log( "error:" + xhr.responseText);
}
}
xhr.open('POST', requestUrl, true);
// xhr.setRequestHeader("Content-Type","multipart/form-data; boundary=----WebKitFormBoundarynA5hzSDsRj7UJtNa");
xhr.send(formData);
return false;
}
Why to reinvent the wheel. Just use Jquery Form Plugin, here. It has example for multipart upload as well.
You just need to set input type as file. You will receive files as input stream at server (off course they will be multipart)