Set a media file to direct download?

Our website will feature “download file” links for assets like PDF files.

I’d like to know if there’s a way to set a media file to direct-download?

I see that there is an “attachment” type, but when I limit the model to only accept that type and upload a file, it doesn’t affect a new download behavior, it just uses the mime type of the file and errors when I try to publish. (The error shown is: ‘“Attachment” are the only acceptable file types’)

We don’t want to have to do tricks to make a file downloadable… is there a way to make a file downloadable in the contentful UI? If not, can you please file a feature request for that?

Thank you

1 Like

Update:

I was able to get downloads working by using the npm module downloadjs.

My typescript code looks like this:

      url?: string;

      constructor(props: DownloadLinkProps) {
        super(props);
        try {
          const { url } = this.props.data.fields.file.fields.file;
          if (url.slice(0, 2) === '//') {
            this.url = `https:${url}`;
          } else if (url.slice(0, 4) === 'http') {
            this.url = url;
          } else {
            throw new Error(`Invalid file download URL: '${url}'`);
          }
        } catch (e) {
          console.error(e);
        }
      }

      handleClick = () => {
        if (this.url) {
          download(this.url);
        }
      };

Hi @moses.gunesch,

Thanks for sharing your update with us :slight_smile:
Just to clarify, are you now uploading these assets through the Web Interface or the JS SDK?

Via the web interface.

That’s what I was suggesting could use an option to make an asset downloadable, either in the data model’s settings or per-asset.

Would make most sense at the data model level since a “FileDownload” model would be self-managing for editors, without adding a requirement that they remember to check a box every time.

Media urls are delivered as protocol relative urls (e.g., //images.cfassets.net/space/...) and should use whatever protocol the referring webpage is using (i.e., http or https). If you want to statically set it, just append https: to the beginning of the url string.

Also check out the MDN page about Content Disposition which directs a web browser to download the link as a file or try to display it inline. How exactly to set this header will depend on your specific frontend setup.

Also check out the MDN page about Content Disposition which directs a web browser to download the link as a file or try to display it inline. How exactly to set this header will depend on your specific frontend setup.

No matter what frontend setup one may have, frontends can’t set Response Headers.

The MDN article you have suggested is a great thing to add to the Contentful API, it would actually be great if consumers of the API could do something like this:

GET http://images.cfassets.net/<space_id>/<...>/some-file.png?w=400&download=1

Without the download=1 query param, the image would load inline as usual.

With the download=1 query param, then whatever codebase that the Contentful API is using to serve Contentful assets would set the Content-Disposition header you have suggested before serving the asset.

Thoughts?

UPDATE: Anyone who stumbles upon this might want to check out:

In theory this could be solved using the download attribute, but I’ve noticed that browsers tend to respect the origin servers’ headers more.

I have the same problem. I want to have links which will cause the browser to download a PDF when clicked. I can create a download link:

<a href="https://downloads.ctfassets.net/..." download>Download</a>

This works for images but Chrome ignores the download attribute for PDFs and instead navigates to the PDF URL.

I would like to request a feature where a query parameter could be added to cause the server to send the Content-Disposition header as mentioned by brandon.jimenez.

1 Like