Prompt file download with XMLHttpRequest

后端 未结 3 1912
清歌不尽
清歌不尽 2020-12-08 00:36

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 XMLHttp

相关标签:
3条回答
  • 2020-12-08 01:13

    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 hidden form with target=_blank

    UPD: this answer is not accurate anymore since the introduction of Blob API. Please refer to Steven's answer for details.

    0 讨论(0)
  • 2020-12-08 01:20

    download: function(){
        var postData = new FormData();
    		var xhr = new XMLHttpRequest();
    		xhr.open('GET', downloadUrl, true);
    		xhr.responseType = 'blob';
    		xhr.onload = function (e) {
    			var blob = xhr.response;
    			this.saveOrOpenBlob(blob);
    		}.bind(this)
    		xhr.send(postData);
     }
    
    saveOrOpenBlob: function(blob) {
    		var assetRecord = this.getAssetRecord();
    		var fileName = 'Test.mp4'
    		var tempEl = document.createElement("a");
        	document.body.appendChild(tempEl);
        	tempEl.style = "display: none";
            url = window.URL.createObjectURL(blob);
            tempEl.href = url;
            tempEl.download = fileName;
            tempEl.click();
    		window.URL.revokeObjectURL(url);
    	},

    Try this it is working for me.

    0 讨论(0)
  • 2020-12-08 01:30

    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 (this, event) {
        var blob = this.response;
        var contentDispo = this.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'));
    }
    
    0 讨论(0)
提交回复
热议问题