John John - 2 months ago 20x
Javascript Question

In Javascript how can I redirect an Ajax response in window location

I currently have the following working piece of code (angular but applies to any JS framework):

var url = '/endpoint/to/my/file';

method: 'GET',
url: url
.success(function(jdata) {
window.location = url;
// display errors on page

The above is called after a form was completed and the user has clicked on "submit" (the real situation is a bit more complex than this but it is the same idea). I do the form check asynchronously, so there's no page reload.

If the request is successful, returns a binary (a pdf file), if not succesful, the request returns a 400 BadRequest with errors formatted in JS. So what I do is, if successful, I redirect to the same url to have the PDF otherwise I get the JSON error object and do something with it.

How can I refrain from making two requests if the requests is successful?

  • Note1: on the backend side I would like to keep only one route that does everything, check + return PDF

  • Note2: the current situation is pretty neat in my opinion, since I have an asynchronous form check and if successful the file downloads directly in the browser since I have
    "CONTENT-DISPOSITION" -> "attachment"
    in the HTTP header of the successful response

Any idea appreciated


The real deal

The best you could do is split your endpoint.

  1. One for the form and the convenience of having errors without refresh.
  2. Then, on success, redirect to your other endpoint which only downloads the file.

If it's required to be authenticated to access the file, you can hide the file behind a normal endpoint and return the file using X-Accel-Redirect header with nginx or X-Sendfile using apache.

The hack

Disclaimer: This is more of a hack than the best solution. As mention by @Iceman, Safari, IE, Safari-iOS, Opera-mini and some such browsers dont support this particular spec.

In your server-side endpoint, if the file is available without errors, you can set the header to the content-type of the file (like 'application/pdf') so the download will starts automatically.

If there are errors, don't set the header and return a json of the errors to inform the user through javascript.

Since we don't know what's behind, here's a python (Django) example:

response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=your_filename.pdf'
return response

You can handle the response in the ajax success callback:

    url: 'endpoint.php',
    success: function(data) {
        var blob = new Blob([data]);
        var link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob); = "filename.pdf";;

You could also try the jQuery fileDownload plugin mentioned in this answer.