Yaron Schwimmer
Yaron Schwimmer

Reputation: 5357

Content-Disposition:attachment not triggering download dialog

I've encountered some unexpected behavior when trying to create a file download functionality on my NodeJS server. I have a REST (express) API that calls for some export data function, which creates a CSV file on the server and uses res.download('path/to/file') to trigger the download. Response headers include

Content-Disposition:attachment; filename="indicators.csv"
Content-Length:30125
Content-Type:text/csv; charset=UTF-8

so everything seems to be in order.

The thing is, I get the response from the server as plain text. The response has all the data the CSV file contains, but does not trigger the browser's file download dialog like I intended. I tried both on Chrome and FF. The problem persists in both.

Any ideas?

Update

I managed to make it work by creating a dummy form, and using its submit action to make my AJAX call. But it's an ugly hack, and I'm still looking for a more elegant solution.

Upvotes: 23

Views: 35795

Answers (4)

MonoThreaded
MonoThreaded

Reputation: 12043

Inspired by Roman Pletnev, I recommend to wrap up the API response into a made up new document as follows (Vue/csv response):

    API.get(apiName, path, myInit)
        .then((response) => {
            // console.log(response)
            // Wrap this response into a temporary page that will trigger the download
            const blob = new Blob([response.data], { type: 'text/csv' })
            const blobURL = window.URL.createObjectURL(blob)
            const tempLink = document.createElement('a')
            tempLink.style.display = 'none'
            tempLink.href = blobURL
            tempLink.download = 'filename.csv'
            tempLink.setAttribute('target', '_blank')
            document.body.appendChild(tempLink)
            tempLink.click()
            document.body.removeChild(tempLink)
            window.URL.revokeObjectURL(blobURL)
        })
        .catch((error) => {
            console.log(error)
            console.log(error.response);
        });

Upvotes: 0

Pawel Zieminski
Pawel Zieminski

Reputation: 534

The question looks similar to this one

Show 'Save as' dialog box while downloading file from an Iframe through PHP

The basic idea is the second option that Roman described above, but this one's using an iframe to achieve it.

Upvotes: 0

Roman Pletnev
Roman Pletnev

Reputation: 6138

Headers are not the issue. The issue is that you are querying the download url via an ajax call, which will not invoke the browser download dialog. Your options boil down to the following:

  1. Use a form that is submitted to your download url. Instead of having a visible form a user has to interact with, create a form with JavaScript and submit it programmatically by calling form.submit - Handle file download from ajax post

  2. Point window.location to the download url. You can do this in the current window - download file using an ajax request , or in a new one - res.download() not working in my case

Upvotes: 39

MQ87
MQ87

Reputation: 1058

You can try to use a different content-type, so that won't be open as a text file on the browser:

Content-Type:application/ms-excel; charset=UTF-8

Another alternative could be to use application/octet-stream as mime-type to define it as a downloadable file without a better description.

Content-Type:application/octet-stream; charset=UTF-8

Upvotes: 1

Related Questions