To piggyback on my previous question here:
How do I block uploads that lack "DateTimeOriginal" exif data with Fine Uploader?
Once I've got the exif data, I'd like to pass it on to my server within the uploadSuccess AJAX call.
I'm aware of being able to add params, but what I don't see in the docs is some way to do something like:
uploadSuccess: {
params: function(id) {
var params = {
DateTimeOriginal: timestamps[id]
}
return params;
}
}
Is there an equivalent way to handle this?
Upon deeper documentation digging, I found this method:
this.setUploadSuccessParams
Which does the trick.
http://docs.fineuploader.com/api/methods-s3.html#setUploadSuccessParams
Related
UPDATE2: I revisited this issue and have solved the problem by carefully following the doco linked below. But first, for those who are struggling with this, you are in good company. There are so many versions of the doco from Google it is confusing! Do you include platform.js or client.js in your html? Do you load gapi.auth or gapi.auth2? Do you use gapi.auth2.render or gapi.auth.authorize, or gapi.auth2.init, and so on.
The way that returns an access_token (as of this article date) is linked below. I managed to get this working by carefully following the guide and reference using platform.js. Other libraries are then dynamically loaded such as client.js using gapi.load('drive', callback).
https://developers.google.com/identity/sign-in/web/listeners
https://developers.google.com/identity/sign-in/web/reference
==== ORIGINAL ISSUE FOR PROSPERITY ====
UPDATE 1:
I've updated the code sample to do a recursive search of the googleUser object. At least this shouldn't break in a subsequent library.
Below is a code snippet to handle an issue where the access_token in the Google gapi.auth2.AuthResponse object is not at the top level... it is hidden :( in the depths of the object!
So it is retrievable, but not at the top level!!?? I've noticed it seems to be a timing issue... once the application is running for a while on subsequent checks, it does contain the access token at the top level!!
var authResponse = _.googleUser.getAuthResponse();
_.id_token = authResponse.id_token; // Always exists
// access_token should also be a param of authResponse
if (authResponse.access_token) {
debug("Worked this time?");
_.access_token = authResponse.access_token;
} else {
// !!! Internal object access !!!
debug("Attempt to get access token from base object.");
_.access_token = _.objRecursiveSearch("access_token", _.googleUser);
if (_.access_token) {
debug("Access token wasn't on authResponse but was on the base object, WTF?");
} else {
debug("Unable to retrieve access token.");
return false;
}
}
_.objRecursiveSearch = function(_for, _in) {
var r;
for (var p in _in) {
if (p === _for) {
return _in[p];
}
if (typeof _in[p] === 'object') {
if ((r = _.objRecursiveSearch(_for, _in[p])) !== null) {
return r;
}
}
}
return null;
}
I'm guessing getAuthResponse somehow provides a callback once it is ready, but I can't see where in the API.
https://developers.google.com/identity/sign-in/web/reference
I know this question is fairly old, but it appears first when googling for ".getAuthResponse() doesn't have access_token," which is how I got here.
So for those of you in 2016 (and maybe later) here's what I have found out
There's a secret argument on .getAuthResponse, not documented anywhere I have found. If you would run the following in your app
console.log(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse);
You would see that you get the following (copy/pasted from my console)
function (a){if(a)return this.hg;a=.HE;var c=.rf(this.hg);!a.Ph||a.dL||a.Lg||(delete c.access_token,delete c.scope);return c}
This shows that the .getAuthResponse() function looks for an argument, and as far as I can tell doesn't even check its value -- it simply checks if it is there and then returns the whole object. Without that function, the rest of the code runs and we can see very clearly it is deleting two keys: access_token and scope.
Now, if we call this function with and without the argument, we can check the difference in the output. (note: I used JSON.stringify because trying to copy/paste the object from my browser console was causing me some issues).
console.log(JSON.stringify(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse()));
console.log(JSON.stringify(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(true)));
getAuthResponse() object
{
"token_type":"Bearer",
"login_hint":"<Huge mess of letters>",
"expires_in":2112,
"id_token":"<insert your ridiculously long string here>",...}
getAuthResponse(true) object
{
"token_type":"Bearer",
"access_token":"<an actual access token goes here>",
"scope":"<whatever scopes you have authorized>",
"login_hint":"<another mess of letters>",
"expires_in":2112,
"id_token":"<Insert your ridiculously long string here>",
...}
Figured out the fix for this. Turns out that if we don't provide the login scope config in gapi.auth2.init it doesn't return access_token in getAuthResponse. Please call gapi.auth2.init as given below and access_token will be present.
gapi.auth2.init({
client_id: <googleClientID>,
'scope': 'https://www.googleapis.com/auth/plus.login'
})
Here is my resource:
var app, deps;
deps = ['ngGrid', 'getUsers'];
angular.module('getUsers', ['ngResource'])
.factory('users', function ($resource)
{
return $resource('/Admin/GetUsers', {}, {
query: { method: 'GET', IsArray: true }
});
});
and then I've added code to try to add a step to force parsing:
$scope.myData = users.query(function(response)
{
if (typeof (response) == string)
{
response = JSON.parse(response);
}
});
But it never gets this far, and here's the error in Chrome:
Error: [$resource:badcfg] object
http://errors.angularjs.org/1.2.14/$resource/badcfg?p0=array
at http://localhost:23002/Scripts/angular.js:78:12
at a.module.factory.f.(anonymous function).p.then.m.$resolved (http://localhost:23002/Scripts/angular-resource.min.js:8:517)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at http://localhost:23002/Scripts/angular.js:11132:26
at Scope.$get.Scope.$eval (http://localhost:23002/Scripts/angular.js:12075:28)
at Scope.$get.Scope.$digest (http://localhost:23002/Scripts/angular.js:11903:31)
at Scope.$get.Scope.$apply (http://localhost:23002/Scripts/angular.js:12179:24)
at done (http://localhost:23002/Scripts/angular.js:7939:45)
at completeRequest (http://localhost:23002/Scripts/angular.js:8142:7)
Of course I searched for that error, but I found advice to set IsArray to true or false, this makes no difference. If I set a breakpoint and call JSON.parse on the response string, it gets turned into an array of objects, exactly like what I want. So the string is perfectly valid JSON, but angular appears unwilling to parse it as such, it accepts it as a string and then dies.
My controller is very simple:
public List<ApplicationUser> GetUsers()
{
return AdminUsersViewModel.AllUsers;
}
and then, that method uses a LINQ query to get users from the DB, and then iterates over that collection to create a new one, because before I did that, it just blew up. I've made the call in the browser, and see the same string that is appearing in the angular code.
What I need to know is, why isn't angular spotting that this is a collection of objects, and how can I either force it to parse the string, or change the format so angular can tell what it is ?
Thanks for looking.
OK, I got it. I thought the help I read said to use IsArray ( in hindsight, I think it said DON'T use IsArray ). I knew that was non standard, but that's what I did. I ran the non minified version, and found my error. Change to isArray, and it works.
Thanks for looking :-)
I'm working on handling file uploads using express.js and node, and have the basic functionality working. What I need is to implement some security measures -- namely, to limit uploads to certain formats (PNG, JPEG). Is there an easy way to only allow certain formats? Would it go in the body-parser?
app.use(express.bodyParser({
uploadDir: __dirname + '/public/uploads',
keepExtensions: true }));
app.use(express.limit('4mb'));
Are there any other security measures that I should take into account? Is it generally a good idea to wipe EXIF data from the image?
Thanks,
Ben
According to the documentation for connect's bodyParser, any options are also passed to formidable, which does the actual form parsing.
According to formidable docs, you can pass your own onPart handler:
incomingForm.onPart(part)
You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any 'field' / 'file' events processing which would occur otherwise, making you fully responsible for handling the processing.
incomingForm.onPart = function(part) {
part.addListener('data', function() {
// ...
});
}
If you want to use formidable to only handle certain parts for you, you can do so:
incomingForm.onPart = function(part) {
if (!part.filename) {
// let formidable handle all non-file parts
incomingForm.handlePart(part);
}
}
Taken together, you should be able to do something like this:
function onPart(part) {
if(!part.filename || part.filename.match(/\.(jpg|jpeg|png)$/i)) {
this.handlePart(part);
}
}
app.use(express.bodyParser({onPart: onPart});
Warning: I haven't tested any of this.
I found a potential solution:
In your middleware,
if (req.files[key].type != 'image/png' && req.files[key].type != 'image/jpeg'){
res.send(403);
} else {
next();
}
update: This doesn't actually stop the file from uploading, though.
I have a simple ExtJs (3.4) Grid with a Writer. When the user makes some changes the store is saved to the server as follows:
store.on('save', afterSave(resp));
All is fine. However, I want to get a response as to wheather the record has been saved successfully, failed or an update conflict happed. How to best do this?
Are you using Ext.data.proxy.Ajax to load your stores? If so, you can use the reader property to evaluate and handle the server responses.
Another option would be to make AJAX called directly and handle the responses from there as well
I used exception listener to parse the data as suggested here. But, is this the right way to do this.
Ext.data.DataProxy.addListener('exception', function(proxy, type, action,
options, res) {
if (type == 'response') {
var success = Ext.util.JSON.decode(res.responseText).success;
if (success) {
console.log('UPDATE OK');
} else {
console.log('UPDATE FAILED');
}
}
});
Sorry if this question is duplicated but I couldn't solve my problem from other solutions.
I've got this code in a sepate file included in my main index:
var getSuggestedData = {
serviceURL: $("input[name=suggestedServices]").val(),
dataR:"",
doRequest:function(){
//request data to controller
$.ajax({
url:this.serviceURL,
success:function(msg){
this.dataR = msg;
}
})
}
}
When I'm trying to get the variable "dataR" from my index this way it's UNDEFINED! PLEASE, can someone help me out?
$().ready(function() {
getSuggestedData.doRequest();
alert(getSuggestedData.dataR);
});
Thank you in advance!
The reason you are not able to access the dataR object is because it is not in the same context as the result returned from the success method.
One technique is to hold a reference to this in a variable as shown below:
var self = this;
using the jquery library!
$(this.button).bind('click',{self:this},function(event)
{
var that = event.data.self;
alert(that.num);
});
You can also check out the post below in which I explained in detailed about the "this" keyword.
http://azamsharp.com/Posts/57_I_mean__this__not__this_.aspx
If memory serves me right...
this.dataR = msg;
probably needs to be
getSuggestedData.dataR = msg
the 'this' reference would be to the object fed to jQuery, you need to reference the original object. I forget if you could access it by its name directly such as this or if you need to use another method, let me know if it doesn't work out though.