Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IE9 Post just hangs in there, does not return anything #163

Closed
saidoze opened this issue Mar 18, 2014 · 31 comments
Closed

IE9 Post just hangs in there, does not return anything #163

saidoze opened this issue Mar 18, 2014 · 31 comments

Comments

@saidoze
Copy link

saidoze commented Mar 18, 2014

When calling the function $rootScope.upload = $upload.upload({...}); nothing is happening, this is the last line i can log in my console.

Whilst in Chrome/Firefox it uploads perfectly. It's like it won't find my url to post to, but when i change it to a wrong one, it still does not do anything.

Am i missing something specific for IE?

@danialfarid
Copy link
Owner

Yes read the Old Browsers section of the README and follow the instructions.

@andreipopovici
Copy link

Hi Danial,

I have the same issue and I can't pinpoint the error. It just doesn't give me any feedback.

I have both FileAPI.min.js and FileAPI.flash.swf loaded (they're in the same folder as angular-file-upload.min.js). I've also loaded angular-file-upload-shim.min.js before angular.js and angular-file-upload.min.js.

I still get no console output or browser reaction when calling $upload.upload().

Any suggestions where I might look for an error or solution?

Thanks!

@andreipopovici
Copy link

I just noticed a typo in the bundled version of FileAPI.min.js, at line 24: chunkUpoloadRetry instead of chunkUploadRetry

I'm not sure if it affects anything, since the online demo has it too, and it works fine in IE9.

I'm still trying to figure out why it won't upload. I've traced the issue to xhr.__fileApiXHR = FileAPI.upload(config); (line 127 in angular-file-upload-shim.js, but I'm not sure what inside FileAPI.upload is silently failing.

@basilikum
Copy link

I have the same problem. I realized that my server responds with 403 and that the CSRF header, that I define in $upload.upload, is not present anymore in this config variable:

xhr.__fileApiXHR = FileAPI.upload(config);

It's really just a step in the dark but could that be the problem?

@danialfarid
Copy link
Owner

If the Demo page is working for you then the problem is either in your code or the way you customize the plugin.
Try to compare it with the Demo page and see what you are doing differently.

For IE9 Flash should be loaded in place of browse button, one easy way to test it is if you right click on the button it should show the Flash context menu.

Flash has this limitation for setting custom headers, so CSRF headers will not be set for IE8-9. You can workaround this issue to send them as the request data for these browsers or prompt the user that they are using old browser and there are security risks associated with it.

If you couldn't figure it out you can post your html and js code here or create a jsfiddle.

@andreipopovici
Copy link

I'll try to post some code and give some context. Flash is loaded in place of the browse button (right-click brings the context menu), and I'm not currently using CSRF headers. Unlike basilikum, my server never receives a request from the client.

Coffeescript:
$scope.upload = $upload.upload({ url: '/api', data: { email: $scope.dt.dtEmail, views: $scope.dt.views }, file: $scope.dt.dtFile }) .success (data, status, header, config) -> $analytics.eventTrack 'Upload Successful' $scope.dt.submitted = true .progress (event) -> $scope.dt.percentage = parseInt(100.0 * event.loaded / event.total - 3) .error (data, status, header, config) -> console.log data console.log status

$scope.dt.dtFile is a single file object, not an array. I'm debugging all the try/catches in the shim, seems there's a TypeError somewhere in there, just need to dig and find it.

@andreipopovici
Copy link

Not sure if it makes a difference, but I'm also loading https://github.com/es-shims/es5-shim on the same page.

@basilikum
Copy link

Thanks danial, sending the token with the request data did it for me.

@danialfarid
Copy link
Owner

@andreipopovici
Could you also post your html code.

@danialfarid
Copy link
Owner

And yes es5-shim might have conflict with angular-file-upload-shim. Try to load angular-file-upload-shim after es-shim.

@andreipopovici
Copy link

es5-shim is loaded first, before anything else. It turns out it wasn't even loading on IE9 due to a conditional comment.

The HTML is too complicated to explain and post, since it does a bunch of things, including PDF previews using pdf.js (on anything higher than IE9, of course).

I'll try an iframe-based solution for IE9 only, and will revisit this when I get more time.

I can post the includes at the bottom of the HTML, though:

    <script src="bower_components/ng-file-upload/angular-file-upload-shim.min.js"></script>

    <script src="bower_components/jquery/jquery.js"></script>
    <script src="bower_components/angular/angular.js"></script>

    <script type="text/javascript" src="//use.typekit.net/ajv4mph.js"></script>
    <script type="text/javascript">try{Typekit.load();}catch(e){}</script>

    <!-- build:js scripts/plugins.js -->
    <script src="bower_components/sass-bootstrap/js/affix.js"></script>
    <script src="bower_components/sass-bootstrap/js/alert.js"></script>
    <script src="bower_components/sass-bootstrap/js/button.js"></script>
    <!--script src="bower_components/sass-bootstrap/js/carousel.js"></script-->
    <!--script src="bower_components/sass-bootstrap/js/transition.js"></script-->
    <!--script src="bower_components/sass-bootstrap/js/collapse.js"></script-->
    <!--script src="bower_components/sass-bootstrap/js/dropdown.js"></script-->
    <!--script src="bower_components/sass-bootstrap/js/modal.js"></script-->
    <!--script src="bower_components/sass-bootstrap/js/scrollspy.js"></script-->
    <!--script src="bower_components/sass-bootstrap/js/tab.js"></script-->
    <script src="bower_components/sass-bootstrap/js/tooltip.js"></script>
    <script src="bower_components/sass-bootstrap/js/popover.js"></script>
    <!-- endbuild -->

    <!-- build:js scripts/modules.js -->
    <script src="bower_components/angular-resource/angular-resource.js"></script>
    <script src="bower_components/angular-touch/angular-touch.js"></script>
    <script src="bower_components/angular-animate/angular-animate.js"></script>
    <script src="bower_components/angular-cookies/angular-cookies.js"></script>
    <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
    <script src="bower_components/angular-route/angular-route.js"></script>
    <script src="bower_components/angular-slider/build/angular-slider.js"></script>
    <script src="bower_components/angular-slider/lib/modernizr.custom.72715.js"></script>
    <script src="bower_components/ng-file-upload/angular-file-upload.min.js"></script>
    <script src="bower_components/ng-pdfviewer/lib/compatibility.js"></script>
    <script src="bower_components/ng-pdfviewer/lib/pdf.js"></script>
    <script src="bower_components/ng-pdfviewer/ng-pdfviewer.js"></script>
    <script src="bower_components/angulartics/src/angulartics.js"></script>
    <script src="bower_components/angulartics/src/angulartics-mixpanel.js"></script>
    <!-- endbuild -->

    <!-- build:js({.tmp,app}) scripts/scripts.js -->
    <script src="scripts/placeholders.min.js"></script>
    <script src="scripts/app.js"></script>
    <script src="scripts/controllers/main.js"></script>
    <script src="scripts/directives/dropzone.js"></script>
    <script src="scripts/directives/ui-bootstrap-popover.js"></script>
    <script src="scripts/filters/main.js"></script>
    <!-- endbuild -->
  </body>

@danialfarid
Copy link
Owner

So what's the error message you get in the console?
Is the $files object empty? Can you console log $scope.dt.dtFile.
Could you also post here the content of config at this line:
xhr.__fileApiXHR = FileAPI.upload(config);

Here is the point that it sends the data to the FileAPI plugin. If it fails there there should be an error code.

Also make sure that you are using the exact same version of FileAPI that is provided with this plugin (do not include FileAPI in the script tag)

@andreipopovici
Copy link

The screenshot below shows the argument sent to FileAPI.upload (so it's the content of config).

I'm not including FileAPI.min.js in the HTML, it comes from the shim. By the way, there's a typo in the provided version, do a search for chunkUpoloadRetry. Not sure it has anything to do with the current error.

screen shot 2014-03-21 at 3 03 08 pm

It never fails anywhere, no errors show up in the console at all, not even from FileAPI's a.log calls that override the console. But in debugging, at line 64 of FileAPI.min.js, at this section:

try{return a.log("(js -> flash)."+c+":",e),p.get(d.flashId||d).cmd(c,e)}catch(g){a.log("(js -> flash).onError:",g),f||setTimeout(function(){p.cmd(d,c,e,!0)},50)}}

the contents of g are:

screen shot 2014-03-21 at 3 11 55 pm

Stepping through never raises any other console error, it just silently moves forward. I can't figure out where in the upload process it fails and why. It's clearly on my side, since your demo works fine in the same browser.

@danialfarid
Copy link
Owner

Can you use non-minified version of FileAPI from here: https://raw.githubusercontent.com/danialfarid/angular-file-upload/master/demo/war/js/FileAPI.js

Just replace it with FileAPI.min.js in your bower_components.

This will give you a better clue what variable is excepted to be Object but it is not.

@andreipopovici
Copy link

It wasn't loading the Flash file at first, because staticPath was set to the default ./dist/, took me a while to figure it out :)

And when it loads the Flash object, it's a child of <body> instead of the input element, so it's hard to find on the page. Once I click it and select a file, the upload goes through! No errors (that I could find) in the unminified version.

However, the .success promise never gets called, and the .progress freezes after the first call, it seems. But server-side, I received the file and processed it.

If I can't find out why the success promise never fulfills, I'll just have to go with a front-end hack to show feedback in IE9 only.

Thank you for the unminified version!

@andreipopovici
Copy link

Hi Danial, just a follow-up question. I still can't figure out why the Flash object isn't correctly nested under the js-fileapi-wrapper div. It works when using the minified FileAPI.min.js, but not when using the un-minified version you linked above (which does make uploads work, though).

My question is: did you change anything between the un-minified and minified versions? Specifically, the code that seems to get called from FileAPI.min.js is:

init: function (){
                    var child = document.body && document.body.firstChild;

                    if( child ){
                        do {
                            if( child.nodeType == 1 ){
                                api.log('FlashAPI.state: awaiting');

                                var dummy = document.createElement('div');

                                dummy.id = '_' + _attr;

                                _css(dummy, {
                                      top: 1
                                    , right: 1
                                    , width: 5
                                    , height: 5
                                    , position: 'absolute'
                                    , zIndex: 1e6+'' // set max zIndex
                                });

                                child.parentNode.insertBefore(dummy, child);
                                flash.publish(dummy, _attr);

                                return;
                            }
                        }
                        while( child = child.nextSibling );
                    }

                    if( _retry < 10 ){
                        setTimeout(flash.init, ++_retry*50);
                    }
                },

Afterwards, the mouseover function receives the event from the object element, when I hover on the 5px by 5px square in the top left (bottom of this code block):

mouseover: function (evt){
                    var target = api.event.fix(evt).target;

                    if( /input/i.test(target.nodeName) && target.type == 'file' ){
                        var
                              state = target.getAttribute(_attr)
                            , wrapper = flash.getWrapper(target)
                        ;

                        if( api.multiFlash ){
                            // check state:
                            //   i � published
                            //   i � initialization
                            //   r � ready
                            if( state == 'i' || state == 'r' ){
                                // publish fail
                                return  false;
                            }
                            else if( state != 'p' ){
                                // set "init" state
                                target.setAttribute(_attr, 'i');

                                var dummy = document.createElement('div');

                                if( !wrapper ){
                                    api.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');
                                    return;
                                }

                                _css(dummy, {
                                      top:    0
                                    , left:   0
                                    , width:  target.offsetWidth + 100
                                    , height: target.offsetHeight + 100
                                    , zIndex: 1e6+'' // set max zIndex
                                    , position: 'absolute'
                                });

                                wrapper.appendChild(dummy);
                                flash.publish(dummy, api.uid());

                                // set "publish" state
                                target.setAttribute(_attr, 'p');
                            }

                            return  true;
                        }
                        else if( wrapper ){
                            // Use one flash element
                            var box = _getDimensions(wrapper);

                            _css(flash.getEl(), box);

                            // Set current input
                            flash.curInp = target;
                        }
                    }
                    else if( !/object|embed/i.test(target.nodeName) ){
                        _css(flash.getEl(), { top: 1, left: 1, width: 5, height: 5 });
                    }
                },

Here's the relevant part from the HTML:

<div class="upload-button">
      <a class="btn btn-info"  href="javascript:;"><span ng-show="dropSupported">or</span> Select PDF File
        <input type="file" name="dtFile" ng-file-select="onFileSelect($files)" accept="application/pdf">
      </a>
</div>

That's the only file input in the entire HTML. It's nested under a container div:

<div class="app"  ng-file-drop-available="dropSupported=true">
      <div ng-include="'views/dropzone.html'"></div>
      <div ng-include="'views/app.html'" class="views-wrapper"></div>
</div>

@andreipopovici
Copy link

I wanted to thank you again for all your help so far, and for writing the service! Sorry for being a pain :)

@danialfarid
Copy link
Owner

The version of non-minified FileAPI is different.
In order for flash to be placed properly you need to be careful about the positioning of the input file element. It might be a css rule that makes the flash object to be misplaced.

@andreipopovici
Copy link

Here's the relevant section from the SCSS file:

  .upload-button {
    position: relative;
    margin-bottom: 3em;
    font-size: 16px;
    font-weight: 600;
    .btn{
      padding: 8px 12px;
    }

    input {
      position: absolute;
      z-index: 2;
      top: 0;
      left: 20%; /* adjust to visually fit over CSS button */
      @include opacity(0);
      background-color: transparent;
      color: transparent;
      width: 60%;  /* adjust to visually fit over CSS button */
      height: 100%;
    }

And the HTML:

    <div class="upload-button">
      <a class="btn btn-info"  href="javascript:;"><span ng-show="dropSupported">or</span> Select PDF File
        <input type="file" name="dtFile" ng-file-select="onFileSelect($files)" accept="application/pdf">
      </a>
    </div>

And here's how it gets rendered in IE9:
screen shot 2014-03-23 at 3 40 05 pm

I'm trying to find where in FileAPI.js the Flash object gets initialized and moved to the correct position. It must be somewhere between the init and mouseover functions...

@danialfarid
Copy link
Owner

I don't think wrapping your input in an a tag would work. Try it outside the a tag or use div instead of a.
Also instead of applying the style to the input element wrap it in a div and apply the style to the div.

There should be an object tag created inside the js-file-api-wrapper div once the FileAPI detects the input file.

  <div class="upload-button">
      <div class="btn btn-info" ><span ng-show="dropSupported">or</span> Select PDF File
        <div class="input-wrapper">
           <input type="file" name="dtFile" ng-file-select="onFileSelect($files)" accept="application/pdf">
        </div>
      </a>
    </div>
...
CSS:

    input-wrapper {
      position: absolute;
      z-index: 2;
...

@andreipopovici
Copy link

Hmm, that might have been a good idea. I ultimately brute-forced it by giving the a fixed dimensions and making the js-fileapi-wrapper be absolutely positioned and sized. The button now works properly across browsers and is positioned where it should be.

I'm now tackling the next issues: progress is not updating properly (I see from the demo code that there's a conditional for IE reporting 200% progress, I'll go ahead and do that too), and the success callback never gets called.

@pkreuzinger
Copy link

Hello Andrei! I ran into the same problems you described and after fixing the 'upoload'-typo got it working to the point where the upload via flash happens, but the success callback is not called, only some progress events get fired. Did you find out, why the callback does not get called?

@andreipopovici
Copy link

I did not find out why, but the un-minified version of the FileAPI.js script seemed to solve the issue.

@albitxu
Copy link

albitxu commented Apr 8, 2014

I'm using minified version of FileAPI.js provided within angular-file-upload module. I ended up in the situation of the uploading freezing only when the file is uploaded properly. I have discovered that this only happens when the response status is 200 and the response text is empty. If a fill in the response text, everything works fine.

Hope this helps you all !

@danialfarid
Copy link
Owner

@albitxu If that only happens for IE8-9 that's a flash bug/limitation. There need to be a response body coming back.

@andreipopovici @pkreuzinger Is there any outstanding issue or possible fix that could be done left here or can I close this issue?

@andreipopovici
Copy link

Well we didn't figure out yet why it works with the un-minified version (at least in my situation), but if you could replace the minified with the un-minified (and let users minify at will using something like Grunt or Gulp), then I vote for closing.

@pkreuzinger
Copy link

Fixing the mentioned typo and returning a non empty response worked for me. Maybe mention that flash limitation in the readme/old browsers section.
Cheers for the great work:)

Am 22.04.2014 um 05:54 schrieb Danial Farid notifications@github.com:

@albitxu If that only happens for IE8-9 that's a flash bug/limitation. There need to be a response body coming back.

@andreipopovici @pkreuzinger Is there any outstanding issue or possible fix that could be done left here or can I close this issue?


Reply to this email directly or view it on GitHub.

@jonjaques
Copy link

This took me a few days to figure out, but I think I know what's wrong.
For me this issue (IE9 hanging) was solved by switching to the non-minified version as mentioned.

As for where the problem lies, if you checkout the Gruntfile and this directory and peep the commit logs, you'll see that the minified version is 3 months older than the non-minified one (and presumably missing the fix for #122 which is when FileAPI.js was updated).

If I have time tomorrow, I'll submit a PR to remedy the problem I described. Long story short is we need to fix the build process so only one copy of FileAPI is used as the source.

@danialfarid
Copy link
Owner

These are fixed in version 1.4.0 and note has been added to README file for the flash bug.

Reopen if you are still having problem.

@fuyi
Copy link

fuyi commented Sep 2, 2014

Seems like the success promise never fire problem persists, I set response text to not be empty, although file is uploaded, client is hanging and never receive answer from server

@danialfarid
Copy link
Owner

The FileAPI version is switched to newer version since 1.5.x.
Could you copy your html and js code here.
What version of angular-file-upload are you using?
If you use the non-minified version of angular-file-upload-shim.js and put a break point here https://github.com/danialfarid/angular-file-upload/blob/master/dist/angular-file-upload-shim.js#L108 then if the beak point is being reached after upload it means that the FileAPI is working properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants