How to render and download a file type in Sanity.io

17 replies
Last updated: May 19, 2022
How to I render a File type that is downloadable
AI Update

To render a downloadable file in Sanity, you'll need to query the file URL and handle the download properly on your frontend. Here's how:

Schema Setup

First, define a file field in your schema:

{
  name: "document",
  title: "Document",
  type: "file",
}

Querying the File

In your GROQ query, get the file URL like this:

*[_type == "yourDocType"] {
  "fileUrl": document.asset->url
}

The key thing to know is that the standard HTML download attribute won't work for files hosted on Sanity's CDN (different origin). Instead, use the ?dl query parameter that Sanity provides:

// React/Next.js example
<a href={`${fileUrl}?dl`}>
  Download File
</a>

Or if you want to specify a custom filename:

<a href={`${fileUrl}?dl=${filename}`}>
  Download {filename}
</a>

Complete Example

export default function FileDownload({ document }) {
  const fileUrl = document.fileUrl;
  const fileName = document.fileName || 'download';
  
  return (
    <a 
      href={`${fileUrl}?dl=${fileName}`}
      className="download-button"
    >
      Download {fileName}
    </a>
  );
}

The ?dl parameter tells Sanity's CDN to set the proper Content-Disposition header, which triggers the browser's download behavior instead of trying to display the file in the browser.

You can find more details in the Sanity file type documentation and this community answer about rendering files.

You’ll need to use a file type as part of your schema. This will enable you to upload documents, such as PDFs in your studio. Then you can get their upload URL in your queries, and create a download feature on your frontend (typically a
<a>
element with the
download
attribute would do).
I have this as a type
{
            name: "installatiesheet",
            title: "Installatiesheet",
            type: "file",
        },
this works and I can upload a file in sanity studio. But what does the snippet look like to render it as

<a>
Well, you’ll need to query that data in your query first.
"url": installatiesheet -> url
And then once you have the URL in he frontend, you can do something like:

<a href={url} download>Download</a>
FYI: the
download
attribute does not work, if the file url has a different origin as the website. See https://html.spec.whatwg.org/multipage/links.html#downloading-resources
That is the case for all files uploaded to Sanity Content Lake.
There are workarounds for this, like using a server-less api request to proxy the file to the client, but I wouldn’t recommend it.
Ah yes, you’re right. In that case, using the
?dl
attribute from Sanity asset pipeline is the way to go I guess: https://www.sanity.io/docs/image-urls#dl-9836df902327
Uhhh, nice! I didn’t knew about this attribute. Thanks!
hmm interesting, how do i use the
dl
attribute?
You would pass it as part of the URL to the document, as mentioned in the documentation.
and how do I fetch the quiry url of that file type?
I showed you above. :)
sorry I'm not that bright hahaha I'm not geting this to work do you have a example for how to use that in
return (
)
and do i need to change something in the content type ?
I mean, I can’t give you much more than what I already shared in that thread. You will need to query the URL to your file as shown in one of my message earlier in this thread, and then you pass that URL to your
<a>
anchor.
Can I render the PDF document as Iframe instead by download?
Thanks
Thanks alot guys I got it working

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?