Skip to content

fix(export): save downloads under the file name sent by the server [DHIS2-22131] - #2301

Open
jason-p-pickering wants to merge 2 commits into
masterfrom
fix/DHIS2-22131-export-filename
Open

jason-p-pickering wants to merge 2 commits into
masterfrom
fix/DHIS2-22131-export-filename

Conversation

@jason-p-pickering

Copy link
Copy Markdown
Contributor

Fixes https://dhis2.atlassian.net/browse/DHIS2-22131

Problem

Since 101.5.0, a compressed export is saved under the uncompressed file name. For example, a data export with ZIP compression is saved as dataValueSets.json, although the file is a ZIP archive.

Commit 9661c61 changed exports to fetch the file first, so the app can show the server's error message, and then save it from a blob URL. A blob URL has no Content-Disposition header, so the browser falls back to the link's download attribute, which locationAssign builds from the request URL. The server still sends the right name, for example attachment; filename="dataValues_2026-07-02_2026-10-02.json.zip", but the app no longer uses it.

Change

  • fetchAndDownload reads the file name from the response's Content-Disposition header and passes it to locationAssign.
  • locationAssign uses that name for the download, and falls back to the name derived from the URL when there is none, as before.
  • New getFilenameFromContentDisposition handles filename="...", an unquoted filename=..., and the encoded filename*=UTF-8''... form, which it prefers.

This applies to every export that uses fetchAndDownload: data, event, metadata, metadata dependency and tracked entity.

Testing

  • New unit tests cover header parsing (quoted, unquoted, encoded, malformed encoding, missing) and locationAssign with a given file name.
  • A new fetchAndDownload test checks that the download link is named after Content-Disposition. It fails without the change, getting the URL-derived name instead.
  • All 24 tests in helper.test.js pass, and d2-style check js passes.
  • On the 2.43.2 RC test instance (bundling 101.5.0), the server returns the expected Content-Disposition names for ZIP, GZip and uncompressed data exports. The app currently saves the ZIP export as dataValueSets.json.

The backend counterpart, DHIS2-22126 (correct Content-Type for compressed data exports), is already merged in core.

🤖 AI Assisted

…HIS2-22131]

Since exports are fetched first and saved from a blob URL (9661c61), the
browser no longer sees the response's Content-Disposition header, so a
compressed export was saved under the name taken from the request URL,
e.g. dataValueSets.json for a ZIP archive.

fetchAndDownload now reads the file name from Content-Disposition and
passes it to locationAssign, which falls back to the URL-derived name
when the header has none. This applies to all exports that use
fetchAndDownload: data, event, metadata, metadata dependency and
tracked entity.

🤖 AI Assisted
@dhis2-bot

Copy link
Copy Markdown
Contributor

🚀 Deployed on https://pr-2301--dhis2-import-export.netlify.app

@dhis2-bot
dhis2-bot temporarily deployed to netlify October 2, 2026 10:05 Inactive
Addresses SonarQube rule S6594.

🤖 AI Assisted
@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@dhis2-bot
dhis2-bot temporarily deployed to netlify October 2, 2026 10:09 Inactive
@jason-p-pickering

Copy link
Copy Markdown
Contributor Author

@tomzemp or @Sharmyn28 feel free to close this once you fix this for real.

This branch was previously deployed

1 inactive deployment
netlify — 4aa0e969 Deployed Oct 2, 2026 by dhis2-bot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants