Discussion on using GROQ queries to download files and resolving asset references in block content.

12 replies
Last updated: May 3, 2023
So I came across this groq query
// GROQ query
*[_type == 'movie'] {
  title,
  "manuscriptURL": manuscript.asset->url
}

// Then you can use the URL in HTML for example like this:
// <a href={`${manuscriptURL}?dl=`}>Manuscript</a>
for downloading files. However, what if the
file
is added to your block content? Is it as simple as doing
  "body": body[]{
    ...,
    _type == 'file' => {
      ...,
      "documentUrl": asset->url
    }
  }

May 3, 2023, 3:59 AM
Neither 😉
You can generate full URLs to any asset — images and files — using just the asset’s ID, dataset and projectId with this library:

https://www.npmjs.com/package/@sanity/asset-utils
May 3, 2023, 6:29 AM
So right now I am doing
    attachments[]{
      ...,
      "documentUrl": asset->url,
      "documentSize": asset->size,
      "documentOriginalFilename": asset->originalFilename,
    }
Is there something for the size and original file name? I am also running into an issue doing
buildFileUrl(attachment._key, { dataset, projectId })
as I am getting
Error: Cannot use 'in' operator to search for 'originalFilename' in cc0020b7ff8d
but it is midnight here so I am probably missing something
May 3, 2023, 7:01 AM
Ah. The original file name and size you would need to resolve. And yes additionally resolve inside your block content.
On another note, try to avoid multiple `-&gt;`’s for the same document. That snippet is resolving the same query three times. Take a look at this section on
High performance GROQ
May 3, 2023, 8:37 AM
Ahh I should do
// Merge a single subquery into the root level of the result
*[_type == "category"] {
  title,
  "slug": slug.current,
  ...(parent-> {
    "parentTitle": title,
    "parentSlug": slug.current
  }) 
}

May 3, 2023, 2:55 PM
Actually it should be this right?
// Return all fields and resolve all fields in all 'categories' references
*[_type == "product" && defined(salePrice) && salePrice < displayPrice]{
  ...,
  categories[]->
}
As I want to return all fields and resolve all fields in my attachments references. So I tried

  "services": *[_type == "service" && references(^._id)]{
    ...,
    attachments[]->
  },
but that returns
attachments
as
null
🤔
May 3, 2023, 3:01 PM
attachments[]->
should resolve all fields from an array of references. If it’s returning null perhaps you’re targeting the wrong field or it is empty.
May 3, 2023, 3:08 PM
🤦‍♂️ it isn't a reference 😆
 attachments: [
    {
      asset: [Object],
      _type: 'file',
      name: 'Senior Connections Resource Guide',
      _key: 'cc0020b7ff8d'
    }
  ],
May 3, 2023, 3:09 PM
So I got the
buildFileUrl
working but just passing in the attachment. However, I want to get the file size if possible as well
May 3, 2023, 3:11 PM
You’ll need to resolve that from the asset reference.
May 3, 2023, 3:12 PM
Does this query look fine? It gives me what I want but was curious if there is any performance improvements I can make
May 3, 2023, 3:14 PM
I’d personally try to cut down on the number of
spread operators that will end up sending you more data than you likely need. But it looks otherwise fine for now!
May 3, 2023, 3:15 PM
Ok one more groq question... Seeing as I can figure this issue out... How would I go about using
buildFileUrl
for a reference in block? So in my query I am currently doing
"body": body[]{
  ...,
  _type == 'file' => {
    ...,
    "documentUrl": asset->url
  }
}
and then passing the URL for the portable text. And this time it does look like it's a reference

{
  asset: {
    _ref: 'file-f4005335534eb49e6edffea0b1596cd211b670e8-pdf',
    _type: 'reference'
  },
  _type: 'file',
  description: 'Maricopa Community Center Senior Programming Calendar for May 2023',
  _key: '96b1944a9636',
  documentUrl: 'MY DOCUMENT URL'
}
However, I would like to cut that
"documentUrl":  asset->url
out and just use
buildFileUrl
if possible but it's coming back as
undefined.undefined
if my query just returns
body
instead of doing
...
May 3, 2023, 3:22 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?