Skip to content

Instantly share code, notes, and snippets.

@nerdyman
Last active May 7, 2024 09:25
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save nerdyman/5de9cbe640eb1fbe052df43bcec91fad to your computer and use it in GitHub Desktop.
Save nerdyman/5de9cbe640eb1fbe052df43bcec91fad to your computer and use it in GitHub Desktop.
Prompt a File Download and respect the Content Disposition Header Using Fetch and FileSaver

Prompt a File Download With the Content Disposition Header Using JavaScript

Set the Server Response Headers

Expose the Content-Disposition header using the Access-Control-Expose-Headers header and set the Content-Disposition header as you would usually.

Access-Control-Expose-Headers: Content-Disposition
Content-Disposition: attachment; filename="example-file.csv"

The method in which to set headers varies from one server framework to another, check you framework's docs to see how best to set these headers.

Fetch the Data Client-side

Install file-saver dependency:

npm i file-saver

Use fetch and file-saver on the client to request and save the file.

import { saveAs } from 'file-saver';

/**
 * Download a file using `filename` specified in `content-disposition` header
 * @param {string} url             - URL to request
 * @param {Object} [fetchProps]    - Optional addtional props to pass to `fetch`
 * @example
 *     await downloadFile('https://example.com/myfile', { credentials: 'include' })
 */
export async function downloadFile(url, fetchProps) {
  try {
    const response = await fetch(url, fetchProps);

    if (!response.ok) {
      throw new Error(response);
    }

    // Extract filename from header
    const filename = response.headers.get('content-disposition')
      .split(';')
      .find(n => n.includes('filename='))
      .replace('filename=', '')
      .trim()
    ;

    const blob = await response.blob();

    // Download the file
    saveAs(blob, filename);

  } catch (error) {
    throw new Error(error);
  }
}

The standalone file for this code can be found here.

Also see: https://stackoverflow.com/questions/43912862/axios-expose-response-headers-content-disposition

@cescoferraro
Copy link

cescoferraro commented Nov 11, 2021

fetch does not includes content-disposition header on the response object

@nerdyman
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment