0

I am trying to provide a secured file serving feature for a site. I have considered a couple of options that fit with my current model:

  1. Using XMLHttpRequest to retrieve the contents of a file, and then offering either display or Save As features based on file type and user preference.

I understand how to use binary Ajax features (blob, arraybuffer) to retrieve binary files and I have seen this shim for implementing the HTML5 Save As feature, but I am concerned about performance with this technique re: large files. I have not tested yet but I don't expect good performance downloading a 1GB+ file using this technique.

  1. setting an HTTP header on a link (see below) so I can pass an authentication token in the header but still have the file served directly to the browser like a normal download rather than going through the trouble of retrieving the contents with XMLHttpRequest.

I would prefer this method because it fits nicely with the current authentication framework and would require very little extra code, but as far as I can tell only Firefox supports what I want to do.

Firefox has the ability to set http headers in network calls not initiated explicitly by JavaScript code using httpChannel: Firefox HTTP channels. Does anyone know whether this functionality is supported in other browsers? I want to be able to set a link, e.g. :

window.location.href = 'blah';

and have code observing network traffic that sets a custom HTTP header:

httpChannel.setRequestHeader("X-Hello", "World", false);

While it is very cool that Firefox can do this, I need a cross-browser solution. I have seen this question:

Setting request header, in a URL

which is basically what I want to do, but the only recommended solution there is setting session cookies, which I am not using.

Community
  • 1
  • 1
Robert Munn
  • 778
  • 7
  • 12
  • This sounds like an XY Problem. What is your use case? – charlietfl Nov 11 '15 at 17:21
  • Perhaps yes, let me restate the problem. – Robert Munn Nov 11 '15 at 18:03
  • 1
    What's wrong with a normal login and only allow authenticated users to download? – PeeHaa Nov 11 '15 at 18:58
  • @PeeHaa that is what it does, but the current auth mechanism uses a token in an http request header with each request, so I either need to use the existing mechanism, which would work with one of the two options I am looking at, or extend the current mechanism with other functionality. – Robert Munn Nov 11 '15 at 22:58

1 Answers1

0

OK, so I built a function using option 1. from my question. Still worried about file size and performance, but here is a basic solution:

viewFile : function( fileItem ) {

    var xhr = new XMLHttpRequest(), token, contentType, filename;

    xhr.onreadystatechange = function() {

        token = xhr.getResponseHeader( "X-Token" );

        if( token !== undefined && token !== null ){
            app.model.set( "token", token );
            sessionStorage.token = token;
        }

        if ( xhr.readyState === 4 ) {
            contentType = xhr.getResponseHeader( "Content-Type" );
            filename = xhr.getResponseHeader( "X-Filename" );
            response = xhr.response;
            var blob = new Blob([xhr.response], { type: contentType } );
            saveAs( blob, filename ); 
        }
    };

    xhr.open( 'GET', "/index.cfm/api/filelocker/" + fileItem.fileid, true );
    xhr.responseType = "arraybuffer";
    xhr.setRequestHeader ( "X-Token", app.model.get( "token" ) );

    xhr.send();     
}

This technique uses the existing auth mechanism. I'll see how well it works with large files.

Robert Munn
  • 778
  • 7
  • 12