Download file via Ajax request
Everything retrieved via Ajax goes into javascript “memory” space. This is because JavaScript can’t interact with disk. That would be a security issue. Ajax is not designed to do this kind of stuff. But as always, there are some tricks … Here is a simple approach of how to get it in a Ruby on Rails based application.
Scenario
Imagine a plugin embeded in a web page that provides a Base64 image encoded. This image should be generated and stored in the server side and then perform an automatic download.
Tech Context
Back-end: Ruby on Rails. Front-end: Jquery.
Solution
Use two methods (actions) in your controllers layer. The first one receives the image (a string representing Base64 codification), decodes this string and writes it into filesystem:
# POST /images
def create
file_path = File.join(IMAGES_PATH, "awesome_image_name.jpeg")
file = File.new(file_path, 'wb')
file.write(Base64.decode64(params[:base64_string]))
file.close
render json: { image_basename: File.basename(file) }
end
The second action will be responsible for the download:
# GET /images/download?image_basename=image_name
def download
file_path = File.join(IMAGES_PATH, params[:image_basename])
file = File.open(file_path)
send_file file.path, type: 'image/jpeg', x_sendfile: true
end
Finally, the Javascript code to interact with these server actions. The idea is to make a POST
request to create the image. Then, using the ‘success’ callback, send a request to second action (with file name as a parameter in this case) in order to perform the download. Do this via document.location.href
(open a new browser window is also valid) and file will start downloading:
function downloadImageBase64(image) {
$.ajax({
type: 'POST',
url: '/images',
data: { base64_string: image },
success: function(response){
document.location.href = '/images/download?image_basename=' +
response.image_basename;
}
});
}
The key here is the Javascript part. Use your favorite language/framework in the server side to decode, write and send the file.