Giter Club home page Giter Club logo

uploadmgr's People

Contributors

cajus avatar cboulanger avatar derrell avatar hkollmann avatar johnspackman avatar level420 avatar odeimaiz avatar valette avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

uploadmgr's Issues

file listener `changeProgress` state never reaches `uploaded`

I have found that when listening to a file's changeProgress event, the file's state never becomes the final state of uploaded'. So something like the following will never execute the the code when the state is uploaded.

let uploader = new com.zenesis.qx.upload.UploadMgr(this.upload, uploadUrl);
uploader.addListener('addFile', function(evt) {
  let file = evt.getData();
  let progressListenerId = file.addListener('changeProgress', function(evt) {
    let file = evt.getTarget();
    let uploadedSize = evt.getData();
    if(file.getState() === 'uploading')
    {
      console.log('uploading...');
    }
    else if(file.getState() === 'uploaded')
    {
      // this is never executed...
      console.log('finished uploading!');
    }
  }
});

I have made a fix by firing the changeProgress data event in File.js _applyState function:

// property apply
_applyState: function(value, oldValue) {
  qx.core.Assert.assertTrue((!oldValue && value == "not-started")
    || (oldValue == "not-started" && (value == "cancelled" || value == "uploading"))
    || (oldValue == "uploading" && (value == "cancelled" || value == "uploaded")));
  // fire the event!
  this.fireDataEvent('changeProgress', value);
}

Demo upload not working and no error given

Derrell Lipman @derrell 13:37
@johnspackman I'm looking at and seeking to understand UploadMgr. Testing it against your server, the demo app tells me it has uploaded my file, but I don't see a multipart/form message being sent, nor any data from my file... yet I get back a 200. Can you enlighten me as to what's going on?

John Spackman @johnspackman 14:00
@derrell so if the request is not multipart/formdata what is it that returns the 200 response?

John Spackman @johnspackman 14:02
basically on modern browsers it uses XMLHttpRequest, and either uses the browser’s native support for FormData to send it as multipart, or uses a FormData shim to achive teh same thing

Derrell Lipman @derrell 14:02
@johnspackman request:
OPTIONS /demoupload HTTP/1.1
Host: www.zenesis.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Access-Control-Request-Headers: content-type, x-file-name, x-requested-with
Accept: /
Referer: http://localhost:8000/Mutualink/wsg.git/frontend/UploadMgr.git/demo/default/source/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
response:
HTTP/1.1 200 OK
Date: Thu, 19 May 2016 12:23:47 GMT
Server: Apache
Allow: GET,HEAD,POST,OPTIONS,TRACE
Content-Length: 0
Connection: close
Content-Type: text/plain; charset=UTF-8

Derrell Lipman @derrell 14:03
@johnspackman That's all that happens, so I'm confused.

John Spackman @johnspackman 14:03
@derrell so an OPTIONS request is the first connection that asks the server what kind of cross site access is allowed; it’s implemented by the browser transparently, and unless the server responds that the request from your server is allowed, thebrowser will return access denies
whats the response for OPTIONS?

Derrell Lipman @derrell 14:04
@johnspackman those two messages are all that are sent in either direction.

John Spackman @johnspackman 14:05
@derrell ah, it looks like the little demo xss server may not be on my site any more

Derrell Lipman @derrell 14:05
@johnspackman What's giving me the 200?
@johnspackman And more importantly, why is the demo telling me "(Completed)" ?

John Spackman @johnspackman 14:06
don’t know, but AFAICR you should get back more than that - like response headers starting Allow-Access-*

John Spackman @johnspackman 14:06
can you setup an upload url on your localhost:8000?
the only thing my server ever did was to allow anyone to upload from any URL, and then delete the file as soon as it arrived

Derrell Lipman @derrell 14:07
I can. I was hoping to work with an existing server first, since I need to create the upload server here and I've never used multer which I think I want to use.
But if yours no longer exists, I'll need to set it up anyway. I'm concerned, though, that it says it worked. Does this indicate a possible UploadMgr bug?
Or maybe it's just a demo bug?

John Spackman @johnspackman 14:08
@derrell possibly. i started migrating it last weekend and i’ll do some more on it next weekend or when I get a mo, but ill add it as an issue so that it gets tracked down

Derrell Lipman @derrell 14:09
I may be a step ahead of you along that path, since I'd like to get this working today.

File size inconsistent between the stages

The com.zenesis.qx.upload.File#size property seems to be floating between the upload stages; only the value reported at uploading stage is byte-precise. All the subsequent stages return file size + size of request headers. Here's a log excerpt (UploadMgr demo app, 116260127 byte file):

083557 uploadmgr.demo.Application[16-0]: Added file payara-4.1.1.161.zip 
083565 uploadmgr.demo.Application[16-0]: payara-4.1.1.161.zip: state=uploading, file size=116260127, progress=0
083796 uploadmgr.demo.Application[16-0]: Upload payara-4.1.1.161.zip: 1899907 / 116260624 - 2% 
083944 uploadmgr.demo.Application[16-0]: Upload payara-4.1.1.161.zip: 14286211 / 116260624 - 12% 
084191 uploadmgr.demo.Application[16-0]: Upload payara-4.1.1.161.zip: 20771307 / 116260624 - 18%
...
086077 uploadmgr.demo.Application[16-0]: Upload payara-4.1.1.161.zip: 116260624 / 116260624 - 100%
086581 uploadmgr.demo.Application[16-0]: payara-4.1.1.161.zip: state=uploaded, file size=116260624, progress=116260624

It would be more natural if the size property would be consistent between the stages and would always reflect the real file size.

Initiate upload when autoUpload disabled.

I use an upload button as a child control and have a member function that runs on the addFile event.

The addFile member function does some checking of the file to meet file size and extension restrictions before calling uploader.getUploadHandler().beginUploads(). It is clear that the addFile event is executing when I add a file, but it appears the the upload handler's __queue is empty when beginUploads() executes.

So, adding one file does nothing, but adding a second file just afterwards ends up uploading both files, even when the multiple flag is set to false.

Here is a trace in the console after adding the first file:

016872 project.sections.user.Profile[362-0]: NAME: IcoNinja_b.jpg SIZE: 32291
016873 project.sections.user.Profile[362-0]: QUEUE: [  ]

So you can see that the addFile event is firing normally but the uploader's queue is an empty array; this may be why no uploads occur. However, upon the second (different) file added, I get:

024531 project.sections.user.Profile[362-0]: NAME: IcoNinja_p.png SIZE: 15785
024532 project.sections.user.Profile[362-0]: QUEUE: [ File[613-0] ]

And we can see the uploader's queue is length 1 (I'm guessing the previously added file) but the two files are in fact uploaded.

024544 com.zenesis.qx.upload.XhrHandler[389-0]: onprogress: lengthComputable=true, total=32748, loaded=32748, headerLength=374
024564 com.zenesis.qx.upload.XhrHandler[389-0]: onprogress: lengthComputable=true, total=16241, loaded=16241, headerLength=374

Child control code:

_createChildControlImpl : function(id)
{
    var control;
    var btnMinMax = 160;
    var imgMinMax = 150;

    switch(id)
    {
        case 'profileBtn' :
            control = new com.zenesis.qx.upload.UploadButton;
            control.set({
                minWidth : btnMinMax,
                maxWidth : btnMinMax,
                minHeight : btnMinMax,
                maxHeight : btnMinMax,
                padding : 5,
                acceptUpload : '.jpg,.png,.gif'
            });
            var img = control.getChildControl('icon');
            img.set({
                minWidth : imgMinMax,
                maxWidth : imgMinMax,
                minHeight : imgMinMax,
                maxHeight : imgMinMax,
                scale : true
            });
            this.add(control);
            this.__uploader = new com.zenesis.qx.upload.UploadMgr(control, "/uploads");
            this.__uploader.set({
                autoUpload : false,
                multiple : false
            });
            this.__uploader.addListener('addFile', this.__addFile, this);
        break;
    }
    return control || this.base(arguments, id);
}

The member function that runs on the addFile event

__addFile : function(e)
{
    var file = e.getData();
    var fileName = file.getFilename();
    var fileSize = file.getSize();

    var ext = fileName.split('.').pop().toLowerCase();
    if(!qx.lang.Array.contains(['jpg', 'jpeg', 'png', 'gif'], ext))
    {
        project.Alert.getInstance().setMessage('Invalid file format!</br>Must be of type JPEG, PNG or GIF.');
        this.__uploader.getUploadHandler().cancelAll();
        //this.info('UPLOADER:', this.__uploader.getUploadHandler().__queue);
        return;
    }
    if(fileSize > 2000000) // 2 MB
    {
        project.Alert.getInstance().setMessage('File too large!</br>Must be 1 MB or smaller.');
        this.__uploader.getUploadHandler().cancelAll();
        //this.info('UPLOADER:', this.__uploader.getUploadHandler().__queue);
        return;
    }
    this.info('NAME:', fileName, 'SIZE:', fileSize);
    this.info('QUEUE:', this.__uploader.getUploadHandler().__queue);

    this.__uploader.setParam("fileName", fileName);
    this.__uploader.setParam("sessionId", project.Model.getInstance().getSessionInfo().SESSION_ID);
    this.__uploader.getUploadHandler().beginUploads();
    var stateListener = file.addListener("changeState", function(evt) {
        var state = evt.getData();
        var file = evt.getTarget();
        if(state == 'uploaded')
        {
            var btn = this.getChildControl('profileBtn');
            btn.setIcon('/uploads/user/' + file.getResponse() + '?nocache=' + Math.random());
        }

        // Remove the listeners
        if (state == 'uploaded' || state == 'cancelled')
        {
            file.removeListenerById(stateListener);
        }
    }, this);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.