How can I set the Accept Header for a link on a we

2019-02-05 22:04发布

This is mostly an ivory tower question, since I can easily just make a new URL endpoint. But basically, I'd like to be able to serve up CSV when the user has the Accept header configured to include text/csv. That's trivial on the server side, but on the client side I don't know how to set the Accept header unless I'm using XHR or some other "non-browser" client. Is there a way in HTML to set the Accept header in a link or in JS to set the Accept header when using window.location?

3条回答
家丑人穷心不美
2楼-- · 2019-02-05 22:10

Update:

I will leave my original answer below for posterity, but I now see that I didn't really answer the question. There isn't a way to do this "natively", the best approach I can think of would be to use a data uri (http://en.wikipedia.org/wiki/Data_URI_scheme) and have AJAX do the work for you:

// aware that you didn't mention jQuery, but you can do this with or without
var download = function(){
    var mime = this.getAttribute('data-mime-type');
    $.ajax({
        accepts: mime,
        success: function(data){
            var uri = 'data:'+mime+';charset=UTF-8,' + encodeURIComponent(data);
            window.location = uri;
        }
    })
    return false;
}

With the same idea used in the example below:

<a href="/some-csv-endpoint" data-mime-type="text/csv">Download CSV</a>

document.querySelectorAll('a[data-mime-type]').onclick = download;


Original Answer

There is no built-in way to force an 'Accept' header on a link (via HTML or Javascript). I think you could pull this off fairly easily using a very small amount of server & client-side code though. Should be easy in any language, my example is PHP:

function get_accepted_headers() {
    $headers = apache_request_headers();
    if(array_key_exists('Accept', $headers)) {
        $accepted = explode(',', $headers['Accept']);
        return $accepted;
    }
    return array();
}

Add a data-accept attribute to your download links:

<a href="/some-csv-file.csv" data-accept="text/csv">Download CSV</a>

Then attach a click event handler to ensure that the user accepts the specified content type:

// will end up with something like: ["text/html", "application/xhtml+xml", "application/xml;q=0.9", "image/webp", "*/*;q=0.8"]
var user_headers = <?=stripslashes(json_encode(get_accepted_headers()))?>;
var click_header_check = function() {
    var accept = this.getAttribute('data-accept');
    if(user_headers.indexOf(accept) == -1) {
        console.log('User does not explicitly accept content-type: %s', accept);
        return false;
    }
    window.location = this.href;
    return;
}

// attach the event listener
document.querySelector('a[data-accept]').onclick = click_header_check;

Not sure if this is what you were looking for, but hope that it helps.

查看更多
家丑人穷心不美
3楼-- · 2019-02-05 22:33

I figure I might as well put this here for the next thousand people looking at the post. You cannot do it.

查看更多
欢心
4楼-- · 2019-02-05 22:35

For those still interested, there is a way to do this in pure javascript.

The following code uses JQuery (https://jquery.com/) and FileSaver.js (http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js) though you could write the respective parts yourself:

//in case of non binary data use:
var type = 'text/xml';
var url = 'http://your_url_here/'
$.ajax({accepts:{text:type},
        url:url,
        processData:false, 
        dataType:'text', 
        success:function(data){             
                saveAs(new Blob([data], {type: type}),'filename.txt');                                                                  
            }, 
        error: function(){
               // Handle errors here
            }
    });
查看更多
登录 后发表回答