Troubleshooting downloadable documents in NextJS using Sanity.io schema and groq queries.

13 replies
Last updated: Jun 13, 2022
Hi all,this

<a href={`${mediaURL}?dl=`}>Manuscript</a>
opens a page with 404 error
but it should be a downloadable document .
AI Update

The 404 error you're experiencing is likely due to an issue with how your mediaURL is constructed, rather than the ?dl= parameter itself. Let me help you troubleshoot this.

First, verify that your mediaURL is a valid Sanity asset URL. When you query a file from Sanity, you need to dereference the asset properly. Your GROQ query should look something like this:

"fileUrl": file.asset->url

The -> operator dereferences the asset reference to get the actual URL. If you're missing this, you might be getting a reference object instead of a URL string, which would cause a 404.

According to the Sanity file field documentation, Sanity does support a ?dl parameter to trigger downloads (since the standard HTML download attribute doesn't work for cross-origin files). The documentation shows it used as ?dl without a value:

<a href={url + '?dl'}>Download</a>

However, I couldn't find official documentation specifying whether ?dl= (with an empty value) should cause issues. To troubleshoot your specific problem:

  1. Check the URL in your browser console: Log mediaURL to verify it's a complete Sanity CDN URL (should look like https://cdn.sanity.io/files/...)

  2. Test the URL without parameters: Try accessing mediaURL directly without ?dl= to confirm the asset exists

  3. Verify your GROQ query: Make sure you're properly dereferencing the asset:

    const query = `*[_type == "yourType"][0] {
      "manuscriptUrl": manuscript.asset->url
    }`
  4. Try the parameter without the equals sign: Use ?dl instead of ?dl= if you want the original filename, or ?dl=manuscript.pdf if you want a custom filename

If the URL itself is valid but you're still getting 404s with the download parameter, that would be unusual and might warrant reaching out to Sanity support with the specific asset URL for investigation.

Hello
user F
, can you share the way you query for
mediaURL
? I suspect that the data of the document (just like with images and videos) is not dereferenced yet. Could you share more Info please 😊
I use the groq like so
const homepageQuery = groq`*[_type == "documentfile"]{
  "documentURL": documentfile.asset->url
}[0]`;
then I use it in the front-end like this

<a href={`${documentfile}?dl=`}>PDF</a>
and return it like so

return {
    props: {
      data: {
        documentfile,
        product: res.productByHandle,
      },
    },
  };
}
now it redirects me to a 404 page
Also sinds I'm using nextjs I should probably use
<link>
instead of

<a>
right?
I will check your query in a sec, but with
<Link>
and
<a>
in NextJS:Link is used for any kind of internal routing, which also handles preload behaviour etc. Since you only use the url here for downloading I would stay with the normal
<a>
.
Ah okay
And about your file issue, I think I need to understand your schema. It seems you have a
document
called
documentfile
which in it has a
file
, am I right?
this is what the schema looks like
export default {
    name: "documentfile",
    title: "DocumentFile",
    type: "document",
  
    fields: [
        {
            title: 'Document',
            description: "Place document here",
            name: 'documentfile',
            type: 'file',
            fields: [
              {
                name: 'description',
                type: 'string',
                title: 'Description'
              }
            ]
          },
    ],
  };
What's the href like in your console in the end?
undefined?dl=
or something?
Thank you for sharing. So I think that one problem with this schema is that you named the document and the file the same, which can be a but unclear and I suspect hinder the query. I would try something like this:

// documentfile.js

export default {
    name: "documentfile",
    title: "DocumentFile",
    type: "document",
  
    fields: [
        {
            title: 'Document',
            description: "Place document here",
            name: 'file',
            type: 'file',
            fields: [
              {
                name: 'description',
                type: 'string',
                title: 'Description'
              }
            ]
          },
    ],
  };
The query would look something like this.

// query

const homepageQuery = groq`*[_type == "documentfile"]{
  "documentURL": file.asset->url
}[0]`;
But If you are embeding the query for
documentfile
within the overall homepageQuery, you might want to try something like this:
//Query 

const homepageQuery = groq`*[_type == "PAGEDOCNAMEorID"]{ …,
  "documentURL": documentfile.file.asset->url
}[0]`;

hmmm something is still off but I do get it returned in console
Then you should be able to use
documentfile.documentURL
(careful with capitalization).
Ah yes that works thank you !
Wonderful! Thank you
user F
💜

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?