jQuery AJAX fetch only headers and decide wether t

2019-06-14 04:56发布

I'm making an AJAX script based on jQuery.ajax() and have come to a point where I should somehow check if the link I'm trying to load is a html page or something different like a swf, image or zip. So I need to somehow check the content-type header and decide if I should get the content also (if it's html) or throw the ajax call away and do a window.location = theUrl. What I don't want is to get the entire file just to find out it's a 100MB zip file.

Is there a way to 'pause' (or abort) the request while its still going and read just the headers ? HEAD call is not an option because this way I would have to make 2 requests to the server every time.

Maybe some sort of hack with setTimeout and low-level xhr functions?

Thanks in advance! :)

EDIT: Tried to get the headers from xhr in setTimeout before the request finished but it doesn't seem to populate it until all of the data has been fetched.

EDIT 2: I hacked my way around the jquery's thing that binds itself to onreadystatechange:

var xhrr = new window.XMLHttpRequest();
$.ajaxSetup({
    xhr: function() { return xhrr }
});

...
$.ajax(....);

var theirfunc = xhrr.onreadystatechange;
xhrr.onreadystatechange = function() {
    console.log('xhr state: ', xhrr.readyState);
    theirfunc();
};

So this gave me states 1, 2, 3, 4 in order and I could get the content-type and abort successfully. I'm still investigating why it won't work when jquery itself creates the XMLHttpRequest object. If I skip the ajaxSetup part and get var xhrr = $.ajax(...) then bind the same way it won't work. So how is my xhr any different than jquery's? I see they do it like this:

function createStandardXHR() {
    try {
        return new window.XMLHttpRequest();
    } catch( e ) {}
}

So it shouldn't make a difference?

EDIT 3: Found it! jquery 1.6 returns a fake xhr object with just a small number of the properties and onreadystatechange is NOT one of them.

3条回答
放荡不羁爱自由
2楼-- · 2019-06-14 05:38

I think if for example you specify:

contentType: "text/html; charset=utf-8"

in your ajax request if the sent data doesn't match the MIME type you specified the request will fail and I think this is how you can go about handling this.

For further information check out this section of the jQuery documentation

Also maybe you can have a go at the beforeSend parameter:

    $.ajax({
  url: 'http://fiddle.jshell.net/favicon.png',
  beforeSend: function( xhr ) {
    xhr.overrideMimeType( 'text/html; charset=x-user-defined' );
  },
  success: function( data ) {
    if (console && console.log){
      console.log( 'Sample of data:', data.slice(0,100) );
    }
  }
});

Hope this helps.

查看更多
甜甜的少女心
3楼-- · 2019-06-14 05:39

You might have to hack jQuery. I don't know how to do this in detail, but...

jQuery uses XMLHttpRequest() to load data. If you look here (mind where the page will be scrolled)

http://en.wikipedia.org/wiki/XMLHttpRequest#The_onreadystatechange_event_listener

you will find that it's somehow possible to attach a listener that listens for the headers to be loaded. The data would then continue to load, but using the abort() function you can abort that. If you look in the jQuery source code:

http://www.google.com/codesearch#LARMQtWqu54/trunk/spec/support/jquery-1.4.4.js&q=xmlhttprequest%20package:jQuery&type=cs

and search for xhr.send (1 match) and window.XMLHttpRequest (2 matches) , you will see that those options are not used by jQuery natively (note that xhr is an XMLHttpRequest). However, in the first match of window.XMLHttpRequest it is indicated in the comments that you can override this object. However, in the second match the comment is not there, so I'm not sure if this would be overridden as well (hence you might need to hack to have it work in all browsers). You would need to extend XMLHttpRequest and modify the constructor and/or send method to call its parent's. Pass that object to jQuery in the way the comments refer to.

I hope you know how listeners work and how object-orientation works in javascript.

查看更多
Root(大扎)
4楼-- · 2019-06-14 05:44

By using type 'HEAD', jQuery will not download the content, it will fetch only the headers.

You can then get them by name, by using getResponseHeader on the returned XHR object.

$.ajax({
        type: 'HEAD',
        url: 'http://example.com/api.php',
        complete: function(xhr) {
            var contentLength = xhr.getResponseHeader('Content-Length');
        }
});

You can also get a list of all the response headers with :

xhr.getAllResponseHeaders()
查看更多
登录 后发表回答