'Blocking execution until user selects an option from the browser's download modal

I'm using window.location.href = some_url in a javascript bit. This brings up a menu from the browser, like so:

enter image description here

This is already happening within a promise - I have other .then() after, but I'd like them to hold on until the user has selected something from that menu.

Any way to access this? Code bits:

    $.ajax({
        url: url,
        type: "POST",
        data: formData,
        contentType: false,
        processData: false
        })
        .done(function(response, jqXHR){
            new Promise(function(resolve, reject){
                if (response.download){
                    console.log("downloading files sent.... ")
                    window.location.href=response.download.url

                    // I'd like to block here on the popup window before moving

                    resolve(response);
                } else {
                    console.log("No downloads.")
                    resolve(response);
                }
                return response
            })
                .then(...)


Solution 1:[1]

Okay, so the real answer is you need to not be lazy and use something like a blob instead. Client-side, something like that:

    $.ajax({
        url: url,
        type: "POST",
        data: formData,
        contentType: false,
        processData: false
        })
        .done(function(response, jqXHR){
            console.log("POST success,")
            if (response.download.url) {
                console.log("content to download")
                fetch(response.download.url)
                    .then(function (resp){
                        let blob = resp.blob()
                        const header = resp.headers.get('Content-Disposition');
                        let filename = header.split(';')[1].split('=')[1];
                        response["filename"] = filename
                        return blob
                        // return resp
                    })
                    .then( function(blob) {
                        // blob = resp.blob()
                        const blob_url = window.URL.createObjectURL(blob)
                        const a = document.createElement('a')
                        a.style.display = "none"
                        a.href = blob_url
                        a.download = response.filename;
                        document.body.appendChild(a);
                        a.click();
                        window.URL.revokeObjectURL(blob_url)
                        // alert("download should be finished now")
                        return response
                    })
                    .then(function (response){
                        if (response.current_page && response.current_page.refresh) {
                            console.log("Refreshing page...")
                            location.reload(true);
                            console.log("Done.")
                        } else {
                            console.log("No refresh.")
                        }
                        return response
                    })
                    .catch((err)=>{console.log(err)} )

Then server-side - I'm using django, but the details would be similar in other frameworks:

        logger.info(f"Creating tmp file for pdf response")
        with tempfile.NamedTemporaryFile() as file:
            file.write(pdf)
            file.seek(0)
            stream = file.read()
        # build the http response
        httpresponse = HttpResponse(content_type='application/pdf;', content=stream)
        httpresponse['Content-Disposition'] = f'attachment; filename={value["filename"]}'
        httpresponse['Content-Transfer-Encoding'] = 'binary'
        return httpresponse

This works, because then I'm waiting on the fetch() call to finish before I move on to build the blob() & recover it locally. In other words, the "waiting" is managed by the fetch()' promise, and it only moves on once the server returned the file.

Then I can refresh the page without worrying, since I have the data in the browser's cache at that point. Loosing the state with a reload() at that point is fine.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 logicOnAbstractions