Tatted up, mini skirt with my J's on [Juicy J x2] J's on my feet J's on my feet J's on my feet So get like me [Verse 1: Miley Cyrus] I be in the club standing on the couch In them Wolf Greys like it's my house Drinking out the bottle, I got no respect Looking like a model, who just got a check I back it up, cause I don't give a damn. Js on my feet, so get like me. 23 23 23 23 23 23 23!!!! See more of Js on my feet, so get like me on Facebook. Mac Miller Js On My Feet is popular Free Mp3. You can download or play Mac Miller Js On My Feet with best mp3 quality online streaming on MP3 Download.
I have a javascript app that sends ajax POST requests to a certain URL. Response might be a JSON string or it might be a file (as an attachment). I can easily detect Content-Type and Content-Disposition in my ajax call, but once I detect that the response contains a file, how do I offer the client to download it? I've read a number of similar threads here but none of them provide the answer I'm looking for.
Please, please, please do not post answers suggesting that I shouldn't use ajax for this or that I should redirect the browser, because none of this is an option. Using a plain HTML form is also not an option. What I do need is to show a download dialog to the client. Can this be done and how?
EDIT:
Apparently, this cannot be done, but there is a simple workaround, as suggested by the accepted answer. For anyone who comes across this issue in the future, here's how I solved it:
So basically, just generate a HTML form with the same params that were used in AJAX request and submit it.
jwfearnCreate a form, use the POST method, submit the form - there's no need for an iframe. When the server page responds to the request, write a response header for the mime type of the file, and it will present a download dialog - I've done this a number of times.
You want content-type of application/download - just search for how to provide a download for whatever language you're using.
Don't give up so quickly, because this can be done (in modern browsers) using parts of the FileAPI:
Edit 2017-09-28: Updated to use File constructor when available so it works in Safari >= 10.1.
Edit 2015-10-16: jQuery ajax is not able to handle binary responses properly (can't set responseType), so it's better to use a plain XMLHttpRequest call.
Here is the old version using jQuery.ajax. It might mangle binary data when the response is converted to a string of some charset.
Jonathan AmendWhat server-side language are you using? In my app I can easily download a file from an AJAX call by setting the correct headers in PHP's response:
This will in fact 'redirect' the browser to this download page, but as @ahren alread said in his comment, it won't navigate away from the current page.
It's all about setting the correct headers so I'm sure you'll find a suitable solution for the server-side language you're using if it's not PHP.
Assuming you already know how to make an AJAX call, on the client side you execute an AJAX request to the server. The server then generates a link from where this file can be downloaded, e.g. the 'forward' URL where you want to point to.For example, the server responds with:
When processing the response, you inject an iframe
in your body and set the iframe
's SRC to the URL you just received like this (using jQuery for the ease of this example):
If you've set the correct headers as shown above, the iframe will force a download dialog without navigating the browser away from the current page.
Extra addition in relation to your question; I think it's best to always return JSON when requesting stuff with AJAX technology. After you've received the JSON response, you can then decide client-side what to do with it. Maybe, for example, later on you want the user to click a download link to the URL instead of forcing the download directly, in your current setup you would have to update both client and server-side to do so.
jwfearnI faced the same issue and successfully solved it. My use-case is this.
'Post JSON data to the server and receive an excel file.That excel file is created by the server and returned as a response to the client. Download that response as a file with custom name in browser'
The above snippet is just doing following
Here we need to carefully set few things at the server side. I set few headers in Python Django HttpResponse. You need to set them accordingly if you use other programming languages.
Since I download xls(excel) here, I adjusted contentType to above one. You need to set it according to your file type. You can use this technique to download any kind of files.
For those looking for a solution from an Angular perspective, this worked for me:
Here is how I got this workinghttps://stackoverflow.com/a/27563953/2845977
I see you've already found out a solution, however I just wanted to add some information which may help someone trying to achieve the same thing with big POST requests.
I had the same issue a couple of weeks ago, indeed it isn't possible to achieve a 'clean' download through AJAX, the Filament Group created a jQuery plugin which works exactly how you've already found out, it is called jQuery File Download however there is a downside to this technique.
If you're sending big requests through AJAX (say files +1MB) it will negatively impact responsiveness. In slow Internet connections you'll have to wait a lot until the request is sent and also wait for the file to download. It isn't like an instant 'click' => 'popup' => 'download start'. It's more like 'click' => 'wait until data is sent' => 'wait for response' => 'download start' which makes it appear the file double its size because you'll have to wait for the request to be sent through AJAX and get it back as a downloadable file.
If you're working with small file sizes <1MB you won't notice this. But as I discovered in my own app, for bigger file sizes it is almost unbearable.
My app allow users to export images dynamically generated, these images are sent through POST requests in base64 format to the server (it is the only possible way), then processed and sent back to users in form of .png, .jpg files, base64 strings for images +1MB are huge, this force users to wait more than necessary for the file to start downloading. In slow Internet connections it can be really annoying.
My solution for this was to temporary write the file to the server, once it is ready, dynamically generate a link to the file in form of a button which changes between 'Please wait...' and 'Download' states and at the same time, print the base64 image in a preview popup window so users can 'right-click' and save it. This makes all the waiting time more bearable for users, and also speed things up.
Update Sep 30, 2014:
Months have passed since I posted this, finally I've found a better approach to speed things up when working with big base64 strings. I now store base64 strings into the database (using longtext or longblog fields), then I pass its record ID through the jQuery File Download, finally on the download script file I query the database using this ID to pull the base64 string and pass it through the download function.
Download Script Example:
I know this is way beyond what the OP asked, however I felt it would be good to update my answer with my findings. When I was searching for solutions to my problem, I read lots of 'Download from AJAX POST data' threads which didn't give me the answer I was looking for, I hope this information helps someone looking to achieve something like this.
I want to point out some difficulties that arise when using the technique in the accepted answer, i.e. using a form post:
You can't set headers on the request. If your authentication schema involves headers, a Json-Web-Token passed in the Authorization header, you'll have to find other way to send it, for example as a query parameter.
You can't really tell when the request has finished. Well, you can use a cookie that gets set on response, as done by jquery.fileDownload, but it's FAR from perfect. It won't work for concurrent requests and it will break if a response never arrives.
If the server responds with a error, the user will be redirected to the error page.
You can only use the content types supported by a form. Which means you can't use JSON.
I ended up using the method of saving the file on S3 and sending a pre-signed URL to get the file.
This is a 3 years old question but I had the same problem today. I looked your edited solution but I think that it can sacrifice the performance because it has to make a double request. So if anyone needs another solution that doesn't imply to call the service twice then this is the way I did it:
This form is just used to call the service and avoid to use a window.location(). After that you just simply have to make a form submit from jquery in order to call the service and get the file. It's pretty simple but this way you can make a download using a POST. I now that this could be easier if the service you're calling is a GET, but that's not my case.
Here is my solution using a temporary hidden form.
Note that I massively use JQuery but you can do the same with native JS.
As others have stated, you can create and submit a form to download via a POST request. However, you don't have to do this manually.
One really simple library for doing exactly this is jquery.redirect. It provides an API similar to the standard jQuery.post
method:
I used this FileSaver.js. In my case with csv files, i did this (in coffescript):
I think for most complicated case, the data must be processed properly. Under the hood FileSaver.js implement the same approach of the answer of Jonathan Amend.
see: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/it'll return a blob as a response, which can then be put into filesaver
To get Jonathan Amendsanswer to work in Edge I made the following changes:
to this
I would rather have posted this as a comment but I don't have enough reputation for that
Here is my solution, gathered from different sources:Server side implementation :
Client side implementation (using jquery):
there is another solution to download a web page in ajax. But I am referring to a page that must first be processed and then downloaded.
First you need to separate the page processing from the results download.
1) Only the page calculations are made in the ajax call.
I hope this solution can be useful for many, as it was for me.