How to validate the filename of an uploaded file in a Sanity schema using the "file" data type.
4 replies
Last updated: Oct 6, 2021
M
Hello everyone! Has anyone ever done any filename validation in a schema with the "file" data type? I'll be periodically uploading newer versions of files and need to make sure I'm not adding the wrong file in any document.
If I try to do document level validation, I don't know how to get the original file name. Doing the following only gets me the hashed filename.
export default { name: 'download', title: 'Download', type: 'document', fields: [ { name: 'name', title: 'Name', type: 'string', validation: (Rule) => Rule.required(), }, { name: 'description', title: 'Description', type: 'string', }, { name: 'filename', title: 'Filename', description: 'This will be the filename which the uploaded file must have.', type: 'string', validation: (Rule) => Rule.required(), }, { name: 'file', title: 'File', type: 'file', validation: (Rule) => Rule.required(), }, { name: 'active', title: 'Active', description: 'Is this download active?', type: 'boolean', initialValue: true, }, ], }
validation: (Rule) => Rule.custom((doc) => { const matched = doc.filename === doc.file.asset._ref; return matched ? 'Uploaded filename does not match the expected filename.' : true return true; }),
Oct 4, 2021, 12:00 AM
Hi User! Sorry for the delay responding.
Thankfully, validation can be async, so you can use a client to dereference the file asset and get the filename:
This is using the client to get the original filename of the fileAsset, then it compares it against the filename field (using the
second parameter of
Thankfully, validation can be async, so you can use a client to dereference the file asset and get the filename:
import sanityClient from 'part:@sanity/base/client'; const client = sanityClient.withConfig({ apiVersion: '2021-10-04' }); export default { name: 'download', title: 'Download', type: 'document', fields: [ { name: 'name', title: 'Name', type: 'string', validation: (Rule) => Rule.required(), }, { name: 'description', title: 'Description', type: 'string', }, { name: 'filename', title: 'Filename', description: 'This will be the filename which the uploaded file must have.', type: 'string', validation: (Rule) => Rule.required(), }, { name: 'file', title: 'File', type: 'file', validation: Rule => Rule.custom(async (doc, context) => { const { _ref } = doc.asset const { filename } = context.document const originalFilename = await client.fetch(`*[_id == $ref][0].originalFilename`, { ref: _ref }) return filename === originalFilename ? true : `Uploaded file ${originalFilename} does not match required filename ${filename}` }), }, { name: 'active', title: 'Active', description: 'Is this download active?', type: 'boolean', initialValue: true, }, ], }
second parameter of
Rule.custom()). If they match, return
true. If they don’t, tell the user why.
Oct 5, 2021, 3:51 AM
M
Thank you so much for this. I would have never thought of doing it that way.
Oct 6, 2021, 3:53 PM
M
Thank you so much for this. I would have never thought of doing it that way.
Oct 6, 2021, 3:53 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.