3

I'm integrating an intranet with a document management system. The DMS has a SOAP API. We've built a client that receives REST calls, makes the SOAP calls, and returns JSON or document data.

The problem is all of the solutions for AJAX filedownload seem to use iFrame (see John Culniver's filedownload plugin).

I can't use this because I need to provide authentication credentials in the header. The only other potential solution I can think of is using window.open (if I can get past browser popup blocking).

Does anyone have another potential solution or how might do this with window.open??

Thanks

Eric H.
  • 6,894
  • 8
  • 43
  • 62

2 Answers2

3

I don't think there is a client-side solution for this problem. window.open isn't going to let you set the request headers. You'll need to do something like send a cookie or some other value to the server and add server-side code that alleviates the need for the request header.

See the answers to:

Community
  • 1
  • 1
ryan
  • 6,541
  • 5
  • 43
  • 68
  • thanks for this. It occurred to me that I may have to build a temporary URL to serve the file and point the user to it. I'm going to see if they're any alternatives and post them here I find any. – Eric H. Mar 17 '13 at 20:21
  • 2
    Alas, we get close by downloading pdf data and [creating a temporary URL.createObjectURL](http://stackoverflow.com/questions/15467747/properly-create-and-serve-pdf-blob-via-html5-file-and-url-apis) but modern browsers aren't quite at the point where we can do this for binary files... At least that's what i found after hours of digging. I'll have to temporarily serve the file and send the doc URL in the AJAX response. Thanks. – Eric H. Mar 18 '13 at 16:03
  • I second @EricH. the only way for the moment would be to create a temp file with unique and random URI , send it back through the Ajax request and download the file in a second link click, or browser redirection. The new path should not have any authentication though – Majid Oct 01 '15 at 18:55
1

I was able to do it successfully. I'm my example I'm using Basic Authentication however you can replace your Authorization header with different value (e.g you can replace it with Bearer Yourtokenvalue.

Here is the code snippet

$(document).on("click", "#btn", function() {

  var username = "yourUserNameForBasicAuthentication";
  var password = "yourPasswordForBasicAuthentication"

  console.log("button clicked");
  var request = new XMLHttpRequest();
  request.open("GET", $("#txtUrl").val().trim(), true);

  //Set the authorization headers
  request.setRequestHeader("Authorization", "Basic " + window.btoa(username + ":" + password));

  //Set the Response type as blob which means raw data
  request.responseType = "blob";

  //We will initiate a default file name in case no file name is detected later on from headers of HTTP Request
  var fileName = "unnamed.pdf";
  request.onload = function(event) {
    if (request.status == 200) {
      console.log("success response received");
      var blob = request.response;

      //Getting contenttype from response headers
      var contentType = request.getResponseHeader("content-type");
      if (contentType == null) {
        contentType = "application/pdf";
      }

      //Check 'Content-Disposition' header to get filename of file (if possible)
      if (request.getResponseHeader("Content-Disposition")) {
        var contentDisposition = request.getResponseHeader("Content-Disposition");
        fileName = contentDisposition.substring(contentType.indexOf("=") + 1);
      }

      if (window.navigator.msSaveOrOpenBlob) {
        // Internet Explorer
        window.navigator.msSaveOrOpenBlob(new Blob([blob], {
          type: contentType
        }), fileName);
      } else {
        var el = document.createElement("a");
        document.body.appendChild(el);
        el.href = window.URL.createObjectURL(blob);
        el.download = fileName;
        el.click();
        el.remove();
        window.URL.revokeObjectURL(el.href);
      }


    } //end of Status code
    else {
      alert("System failed to authenticate");
    }

  } //End of event
  request.send();

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" value="https://yoursamplefile.txt" id="txtUrl" style="width:100%" /><br />
<input type='button' value='Download File' id='btn' />
vibs2006
  • 6,028
  • 3
  • 40
  • 40
  • Works like a charm (at least for small files). I could imagine this causes trouble with big files (probably holds everything in memory and then creates a data URI out of if). – debuglevel Nov 22 '21 at 09:39
  • @debuglevel for big files I guess have to rely on additional factors. May be generating an file with encrypted filename on server side for the specific limited timing seconds might do the trick for you. 1. Authenticate using the usual authentication 2. Server copies from to your upload folder with a base64string filename 3. You give link to download that file 4. Delete that file after some time period or some activity from UI which states that file downloading is completed. – vibs2006 Nov 22 '21 at 10:54