I'm building a webpage using Next.js (version 13) for the frontend and Firebase for the backend. I'm trying to build an <a>
tag on the frontend that, when clicked, will download an mp3 file. Right now, when clicked, it opens in a new tab and plays the mp3 file even though I have added download='filename.mp3'
to the anchor tag. How can I get it to download instead?
My suspicion is that it has something to do with how Firebase storage builds the download URL, but I don't know what to look for or how to test it.
app/components/SongLinks.tsx
'use client'
import { BsDownload } from 'react-icons/bs'
export default function SongLinks({ downloadURL }) {
return (
<div>
{downloadURL ? (
<a href={downloadURL} download='filename.mp3'>
</a>
) : null}
</div>
)
}
There is an app/[songSlug]/page.tsx file that is calling this SongLinks.tsx component and passing the downloadURL
prop to the SongLinks.tsx component after first getting the song data from Firebase and then calling getAudioDownloadUrl()
from the /lib/firebase.ts file. That function looks like this:
/lib/firebase.ts
export function getAudioDownloadUrl({
audioFilePath,
}: {
audioFilePath: string
}): Promise<string> {
return getDownloadURL(ref(storage, audioFilePath))
}
So basically, in testing this particular song, app/[songSlug]/page.tsx passes downloadURL
to SongLinks.tsx with a value of:
"https://firebasestorage.googleapis.com/v0/b/the-second-messenger-website.appspot.com/o/audio%2Fmrpm0_Saving%20Aleah.mp3?alt=media&token=6d473b20-5d1e-4415-ae27-fd41b2cb30bc"
This works well enough to play the mp3 file in a new browser tab, so I'm fairly certain I'm referencing the Firebase storage bucket correctly. What I'm not sure of is if this is causing some cross-origin problem that is preventing the mp3 from being downloadable. IDK...
I have also tried writing the SongLinks component like this:
app/components/SongLinks.tsx
'use client'
import { BsDownload } from 'react-icons/bs'
export default function SongLinks({ downloadURL }) {
const downloadFileAtURL = (url) => {
const aTag = document.createElement('a')
aTag.href = url
aTag.setAttribute('download', 'Saving Aleah.mp3')
document.body.appendChild(aTag)
aTag.click()
aTag.remove()
}
return (
<div id={selectors['song_links']}>
{downloadURL ? (
<a>
<BsDownload
onClick={() => {
downloadFileAtURL(downloadURL)
}}
/>
</a>
) : null}
</div>
)
}
But this version of the component still opens the mp3 file in a new tab instead of downloading it. What am I missing? Please help. Thank you!