14

So I'm attempting to get a progress bar on file uploads on my site. If I simply upload the resource

$.ajax({
    url: $rootScope.URL,  //Server script to process data
    type: 'POST',
    beforeSend: beforeSendHandler,
    success: completeHandler,
    error: errorHandler,
    data: formData,
    cache: false,
    contentType: false,
    processData: false
});

It works perfectly, however if I add the event to listen to progress:

$.ajax({
    url: $rootScope.URL,  //Server script to process data
    type: 'POST',
    xhr: function() {  // Custom XMLHttpRequest
        var myXhr = $.ajaxSettings.xhr();
        if(myXhr.upload){ // Check if upload property exists
            myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // For handling the progress of the upload
        }
        return myXhr;
    },
    beforeSend: beforeSendHandler,
    success: completeHandler,
    error: errorHandler,
    data: formData,
    cache: false,
    contentType: false,
    processData: false
});

I get:

OPTIONS myserver.com/controller/filtercontroller.php? 405 (Method Not Allowed)
  jQuery.ajaxTransport.send 
  jQuery.extend.ajax    
  (anonymous function)  
  jQuery.event.dispatch 
  jQuery.event.add.elemData.handle  
XMLHttpRequest cannot load myserver.com/controller/filtercontroller.php?. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. The response had HTTP status code 405.

So obviously my server doesn't have Access-Control-Allow-Origin and OPTIONS right? But the top 2 lines of filtercontroller.php are:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');

I've tried several different solutions and none have worked for me.

David Mulder
  • 24,033
  • 8
  • 45
  • 104
user3194367
  • 2,657
  • 3
  • 11
  • 10
  • Access-Control-Allow-Headers may not not allow * as accepted value, depending on the server/client implementation - http://stackoverflow.com/a/8719346/2155068 – MjrKusanagi Jun 01 '15 at 14:14
  • 2
    405 is usually issued by the web server itself. So you might check the configuration of your web server. – Markus Müller Jun 01 '15 at 14:17
  • @MjrKusanagi that is irrelevant in this case -- Access-Control-Allow-Origin: * is an acceptable value. – DIMMSum Jun 01 '15 at 14:18
  • Just to confirm -- there is literally nothing else at the top of that php script, correct? It's literally – DIMMSum Jun 01 '15 at 14:27
  • Yes the first lines of the file are ` – user3194367 Jun 01 '15 at 14:29
  • Okay, and you've checked the response using a browser inspector and those headers aren't there? – DIMMSum Jun 01 '15 at 14:30
  • Could you elaborate on that. The error appears in the console between the call and the progressHandlingFunction getting called, in that function a XMLHttpRequestProgressEvent is passed in, then errorHandler gets called an object and the string "error" are passed to it. – user3194367 Jun 01 '15 at 14:40
  • Can anyone help with this? – user3194367 Jun 03 '15 at 15:06
  • It seems your JS is running on WebStorm. Can you check which headers are sent? Do you read some headers? You could add `header('Access-Control-Allow-Credentials: true');` and `header('Access-Control-Allow-Headers: X-header1, X-header2');` – C Würtz Jun 04 '15 at 09:29
  • Have you tried setting "withCredentials" in the ajax call like so?:`xhrFields: { withCredentials: true } ` – RayGe Jun 04 '15 at 16:52
  • Could you try to add this event handler in the ``beforeSendHandler``? The function given there will receive ``XMLHttpRequest`` as it's first parameter. You can register your listeners here like this: XMLHttpRequest.upload.addEventListener("progress", function(evt){ // Handle progress beforeSendHandler(); }, false); – Martijn Jun 04 '15 at 17:06
  • @ReyGe with credentials didn't help. – user3194367 Jun 05 '15 at 14:43
  • @MartijnR I got Cannot read property 'addEventListenerListener' of undefined – user3194367 Jun 05 '15 at 14:44
  • @CWürtz The first header is already present, adding the second header didn't change anything. – user3194367 Jun 05 '15 at 14:44
  • The anonymous function is corrupting your headers. I can only assume that `progressHandlingFunction` is the anonymous function. Please add it to your post and explain where it exists in scope and enclosure level. – Dave Alperovich Jun 06 '15 at 18:07
  • I've changed out the anonymous function call for a named function, it sits on the same scope level as every other handling function. All it does is take a progress event and attempt to spit out the percent. function progressHandlingFunction(e){ var pc = parseInt(100 - (e.loaded / e.total * 100)); toastr.success(pc + "%"); } – user3194367 Jun 08 '15 at 14:08

2 Answers2

6

So, first of all I do not think it has anything to do with your CORS configuration, as it would output different errors. Looking into what can cause the error you are receiving in the context of Azure/IIS I found the following possibilities:

  • You might have an explicit <remove name="OPTIONSVerbHandler" /> in your web.config file. (This is the default in certain cases).
  • The WebDAV module is interfering and you should add <remove name="WebDAVModule"/>

Lastly I just found this answer which might offer some different solutions where you do not set the CORS headers in your PHP file, but instead set them in the server configuration.

Community
  • 1
  • 1
David Mulder
  • 24,033
  • 8
  • 45
  • 104
  • Thank you so much. Changing the remove name resolved the 405 error, but not the Access-Control-blah-blah error, that was resolved by following the link you provided and adding in the custom headers. Enjoy your bounty. – user3194367 Jun 08 '15 at 16:37
0

The header() must be placed before ANY output is sent to the browser, once output is sent to the browser the header() will actually throw a PHP warning which if you aren't seeing isn't being displayed or tracked.

Alternatively you can also do it through .htaccess which would be processed before any of your PHP scripts. This is going on the asumption that you are using apache for your webserver.

Header set Access-Control-Allow-Origin "*"
# below line shouldn't be needed as by default all of those are allowed,
# if you were doing PUT, TRACE, DELETE, etc then you would need it
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Augwa
  • 2,699
  • 10
  • 22