Saltar al contenido principal

Fix hashed filename when downloading a bundled PDF

Updated Jun 17, 2026 ·

Overview​

When a PDF is downloaded from a React or Docusaurus page, the saved filename may include a generated hash.

Example:

Jose Eden-8cfb0a0ef0992e679b77e0160daa4035.pdf

Expected filename:

Jose Eden.pdf

This can happen when the PDF is imported as a bundled asset instead of being referenced as a static file path.

Root Cause​

Bundlers often add a content hash to imported asset filenames. This is useful for browser caching because a changed file gets a new URL.

In this case, the resume PDF was loaded with require.context():

const pdfContext = require.context("../../../assets/site-design/resume", false, /\.pdf$/);
const moduleValue = pdfContext(pdfKeys[0]);
return typeof moduleValue === "string" ? moduleValue : moduleValue.default;

The generated URL points to a hashed file. When the link uses a bare download attribute, the browser may use the filename from that URL.

<a href={resumePdfUrl} className={styles.resumeButton} download>
Download full resume
</a>

Fix​

Set an explicit filename on the download attribute.

const RESUME_DOWNLOAD_FILENAME = "Jose Eden.pdf";

<a
href={resumePdfUrl}
className={styles.resumeButton}
download={RESUME_DOWNLOAD_FILENAME}
>
Download full resume
</a>

This keeps the hashed asset URL for caching, but it tells the browser what filename to use when saving the file.

Why This Works​

The download attribute can be used in two ways:

AttributeBrowser behavior
downloadDownload the file and infer the filename from the URL.
download="Jose Eden.pdf"Download the file using the provided filename.

The second form is better when the file URL is generated by a bundler or build tool.

Validation​

After applying the change:

  1. Build or start the Docusaurus site.
  2. Open the homepage.
  3. Go to the Experiences section.
  4. Click Download full resume.
  5. Confirm the saved filename is Jose Eden.pdf.

Note: The URL can still contain a hash after this fix. The important part is the downloaded filename shown by the browser.

The fix was applied in:

src/components/homepage/Experiences.tsx