"undefined" returned when accessing some listed properties of File object
Asked Answered
I

5

10

I can't seem to access the width or height keys of my object.

I'm using dropzone.js which has an event for addedFile which returns the file and the first param.

so:

var myDropzone = new Dropzone('#dropzone', {url: '/'});

myDropzone.on('addedFile', function(file) {
    console.log(file);
});

The callback works just fine, in my console I see: enter image description here

As you can see, there's clearly the height & width keys available.

myDropzone.on('addedFile', function(file) {
    console.log(file.name); // returns the whole strong
    console.log(file.width); // returns undefined
    console.log(file['width']);  // returns undefined
});

Heres a screenshot:

enter image description here

My question is, why is name available, but not width or height? Is it because they're readonly or something? If that's the case, is it even possible to access it?

Invocation answered 19/9, 2014 at 6:5 Comment(1)
Ah, that did it, 100miliseconds was enough to access it :) is it possible though that sometimes it wont be defined?Invocation
P
10

The File.width property is a DropzoneJS extension and is not a part of the core File API; it is added later.

Dropzone adds data to the file object you can use when events fire. You can access file.width and file.height if it's an image..

If applicable the image size information is made available by the time the "thumbnail" event occurs. It is not guaranteed to be set before this event.

The documentation isn't very clear on this only alluding to "when the thumbnail has been generated", but such is the behavior of the source (see the createThumbnail/resize functions) - the image size is collected when the thumbnail is generated.


The initial behavior is seen because console.log (in browsers, eg. Chrome, that treat it similar to console.dir) displays the "live" object. This in turn has given enough time for the asynchronous thumbnail generation, and associated image dimension gathering, to complete before the browser displays the object's now-assgined properties in the console. (This also explains why using a timeout to read the property value works - even though such is not a reliable approach.)

On the other hand, directly accessing the file.width forces immediate evaluation of the still-not-set property, which results in undefined in the "addedFile" callback.

Palestrina answered 19/9, 2014 at 6:29 Comment(2)
do you think creating a recurrsive callback with a limit would be a better solution to get this data?Invocation
@ShannonHochkins No. The only correct way to get the information is to wait for the thumbnail event to be fired. If successful, this will be invoked at some point after the addedFile event.Palestrina
B
7

So just to make things clear. As user2864740 said, you need to wait for the "thumbnail" event. This would result in this code:

myDropzone.on('addedFile', function(file) {
  myDropzone.on("thumbnail", function(file){            
     console.log(file);   
     console.log(file.width); // returns width
     console.log(file['width']);  // returns width
  });
});

You could even use it in accept method like this:

myDropzone.on('accept', function(file, done){
   myDropzone.on("thumbnail", function(file){
     if(file.width != 728 && file.height != 90){
       done("Resolution is not correct (Super Banner (728x90))");
     } else {
       done();
     }
   });
}
Belding answered 7/6, 2016 at 14:30 Comment(1)
Note that when supporting multiple uploads, it seems like it will fire for every file/thumbnail combination. Adding a uuid check resolves that: if(file.upload.uuid == thumbnail.upload.uuid) { /* do stuff here */ }Watson
A
1

Add a dirty timeout will not work everytime, you will get some indefined when you will send huge files or multiples files.

I got the same headache and personnaly gave up to check width and height before uploading and check in the server side. In fact you can display dropzone errors by returning an header error:

$size = getimagesize(current($_FILES['value']['tmp_name']));

if($size[0] == 840 && $size[1] == 570){
    //perfect
}
else{
    header("HTTP/1.0 406 Not Acceptable");
    echo 'Your image must be 840x570px';
    exit();
}
Anoa answered 6/5, 2015 at 15:49 Comment(0)
T
0

From you to write the code to see nothing wrong, maybe the type of file isn't object but string, you can try the method JSON.parse(file) and then get the key of width.

Tripinnate answered 19/9, 2014 at 6:16 Comment(1)
its definitely an objectInvocation
D
-1

I used timeout 50ms in complete function and undefined is gone.

Demi answered 6/12, 2019 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.