I'm aware that jQuery's ajax method cannot handle downloads, and I do not want to add a jQuery plugin to do this.
I want to know how to send POST data with XMLHttpRequest to download a file.
Here's what I've tried:
var postData = new FormData(); postData.append('cells', JSON.stringify(output)); var xhr = new XMLHttpRequest(); xhr.open('POST', '/export/', true); xhr.setRequestHeader("X-CSRFToken", csrftoken); xhr.responseType = 'arraybuffer'; xhr.onload = function (e) { console.log(e); console.log(xhr); } xhr.send(postData);
I'm working with Django, and the file appears to be sending back to the client successfully. In the network tab in Chrome, I can see gibberish in the preview tab (which I expect). But I want to send back a zip file, not a text representation of the zip file. Here's the Django back end:
wrapper = FileWrapper(tmp_file) response = HttpResponse(wrapper, content_type='application/zip') response['Content-Disposition'] = "attachment; filename=export.zip" response['Content-Length'] = tmp_file.tell() return response
I've searched this for hours now without finding a proper example on how to do this with XMLHttpRequests. I don't want to create a proper html form with a POST action because the form data is rather large, and dynamically created.
Is there something wrong with the above code? Something I'm missing? I just don't know how to actually send the data to the client as a download.
You need to set it according to your file type. You can use this technique to download any kind of files. "We cannot download the file through Ajax, must use XMLHttpRequest". XMLHttpRequest is AJAX by definition.
Retrieving an HTML resource as a DOM using XMLHttpRequest works just like retrieving an XML resource as a DOM using XMLHttpRequest , except you can't use the synchronous mode and you have to explicitly request a document by assigning the string "document" to the responseType property of the XMLHttpRequest object after ...
Both are equally insecure if you make the requests over unsecured connections. Both are equally secure if you make the requests over SSL connections. A request made over an SSL connection might (ultimately) be profoundly non-secure if you aren't protecting the data appropriately on the server, etc.
If you set the XMLHttpRequest.responseType
property to 'blob'
before sending the request, then when you get the response back, it will be represented as a blob. You can then save the blob to a temporary file and navigate to it.
var postData = new FormData(); postData.append('cells', JSON.stringify(output)); var xhr = new XMLHttpRequest(); xhr.open('POST', '/export/', true); xhr.setRequestHeader('X-CSRFToken', csrftoken); xhr.responseType = 'blob'; xhr.onload = function (e) { var blob = e.currentTarget.response; var contentDispo = e.currentTarget.getResponseHeader('Content-Disposition'); // https://stackoverflow.com/a/23054920/ var fileName = contentDispo.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]; saveOrOpenBlob(blob, fileName); } xhr.send(postData);
And here's an example implementation of saveOrOpenBlob
:
function saveOrOpenBlob(blob, fileName) { window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) { fs.root.getFile(fileName, { create: true }, function (fileEntry) { fileEntry.createWriter(function (fileWriter) { fileWriter.addEventListener("writeend", function () { window.location = fileEntry.toURL(); }, false); fileWriter.write(blob, "_blank"); }, function () { }); }, function () { }); }, function () { }); }
If you don't care about having the browser navigate to the file when it's a viewable file type, then making a method that always saves directly to file is much simpler:
function saveBlob(blob, fileName) { var a = document.createElement('a'); a.href = window.URL.createObjectURL(blob); a.download = fileName; a.dispatchEvent(new MouseEvent('click')); }
UPDATE: this answer is not accurate anymore since the introduction of Blob API. Please refer to Steven's answer for details.
ORIGINAL ANSWER:
XHR request will not trigger file download. I can't find explicit requirement, but W3C doc on XMLHttpRequest doesn't describe any special reaction on content-disposition=attachment responses either
You could download file by window.open()
in separate tab, if it was not POST request. Here it was suggested to use a hidden form with target=_blank
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With