Function Signature
parseDataUrl(
file: string
): { binaryString: Buffer; ext: string }
Description
Parses a data URL (base64-encoded string with MIME type) and returns an object containing the binary data as a Buffer and the file extension extracted from the MIME type.
This function is used internally by storeFileLocally but can also be used standalone when you need to process file data without storing it immediately.
Parameters
A data URL string in the format: data:{mimeType};base64,{base64Data}Example: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...
- Must include the MIME type (e.g.,
image/png, application/pdf)
- Must be base64-encoded
- Follows the standard data URL format
Return Value
return
{ binaryString: Buffer; ext: string }
An object with two properties:
The decoded binary data as a Node.js Buffer. This can be used with Node.js file system functions or other binary operations.
The file extension extracted from the MIME type.Examples:
image/png → "png"
image/jpeg → "jpeg"
application/pdf → "pdf"
text/plain → "plain"
How it Works
- Splits the data URL at the comma separator to separate metadata from content
- Extracts MIME type using regex from the first part (e.g.,
data:image/png;base64)
- Decodes base64 string from the second part into a Buffer
- Extracts extension from the MIME type by taking the part after the
/
The function extracts the extension directly from the MIME type. For example, image/jpeg becomes "jpeg", not "jpg". You may need to normalize this in your application if you prefer specific extensions.
Examples
Basic Usage
const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...'
const { binaryString, ext } = parseDataUrl(dataUrl)
console.log(ext) // "png"
console.log(binaryString instanceof Buffer) // true
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
return {
extension: ext,
size: binaryString.length,
type: file.type
}
})
Custom File Processing
import { writeFile } from 'fs/promises'
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
// Custom file processing before storage
const customPath = `/custom/path/myfile.${ext}`
await writeFile(customPath, binaryString)
return { path: customPath }
})
Image Processing
import sharp from 'sharp'
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
// Process image with sharp
const thumbnail = await sharp(binaryString)
.resize(200, 200)
.toBuffer()
// Store thumbnail
const thumbnailDataUrl = `data:image/${ext};base64,${thumbnail.toString('base64')}`
const thumbnailFile: ServerFile = {
...file,
content: thumbnailDataUrl
}
const filename = await storeFileLocally(thumbnailFile, 8, '/thumbnails')
return { thumbnail: filename }
})
Validate File Type
import type { ServerFile } from '#file-storage/types'
const ALLOWED_EXTENSIONS = ['png', 'jpg', 'jpeg', 'gif', 'webp']
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
// Validate file type
if (!ALLOWED_EXTENSIONS.includes(ext.toLowerCase())) {
throw createError({
statusCode: 400,
message: `File type .${ext} not allowed. Allowed types: ${ALLOWED_EXTENSIONS.join(', ')}`
})
}
// Proceed with storage
const filename = await storeFileLocally(file, 8, '/images')
return { filename, ext }
})
Get File Hash
import crypto from 'crypto'
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
// Generate hash of file content
const hash = crypto
.createHash('sha256')
.update(binaryString)
.digest('hex')
return {
hash,
extension: ext,
size: binaryString.length
}
})
Virus Scanning Before Storage
import type { ServerFile } from '#file-storage/types'
// Assuming you have a virus scanning library
import { scanBuffer } from 'some-antivirus-lib'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
// Scan for viruses
const scanResult = await scanBuffer(binaryString)
if (scanResult.infected) {
throw createError({
statusCode: 400,
message: 'File contains malicious content'
})
}
// Safe to store
const filename = await storeFileLocally(file, 12, '/uploads')
return { filename, scanned: true }
})
import sharp from 'sharp'
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString } = parseDataUrl(file.content)
// Convert all images to WebP format
const webpBuffer = await sharp(binaryString)
.webp({ quality: 90 })
.toBuffer()
// Create new ServerFile with WebP data
const webpFile: ServerFile = {
name: file.name.replace(/\.[^.]+$/, '.webp'),
content: `data:image/webp;base64,${webpBuffer.toString('base64')}`,
size: webpBuffer.length.toString(),
type: 'image/webp',
lastModified: file.lastModified
}
const filename = await storeFileLocally(webpFile, 8, '/images')
return { filename, format: 'webp' }
})
Multiple File Processing
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { files } = await readBody<{ files: ServerFile[] }>(event)
const processedFiles = files.map(file => {
const { binaryString, ext } = parseDataUrl(file.content)
return {
originalName: file.name,
extension: ext,
size: binaryString.length,
mimeType: file.type
}
})
return { files: processedFiles }
})
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
const { binaryString, ext } = parseDataUrl(file.content)
// Extract metadata without storing the file
return {
filename: file.name,
extension: ext,
size: binaryString.length,
sizeKB: (binaryString.length / 1024).toFixed(2),
sizeMB: (binaryString.length / 1024 / 1024).toFixed(2),
mimeType: file.type,
lastModified: file.lastModified
}
})
Error Handling
The function throws an error if the data URL is invalid or doesn’t contain a valid MIME type.
try {
const { binaryString, ext } = parseDataUrl(invalidDataUrl)
} catch (error) {
console.error('Invalid data URL:', error.message)
// Error: Invalid data URL
}
Robust Error Handling
import type { ServerFile } from '#file-storage/types'
export default defineEventHandler(async (event) => {
const { file } = await readBody<{ file: ServerFile }>(event)
try {
const { binaryString, ext } = parseDataUrl(file.content)
return {
success: true,
extension: ext,
size: binaryString.length
}
} catch (error) {
throw createError({
statusCode: 400,
message: 'Invalid file data URL format'
})
}
})
Common Errors
Invalid data URL:
Solution: Ensure the file content is a properly formatted data URL with MIME type
Missing MIME type:
Solution: The data URL must include a MIME type (e.g., data:image/png;base64,...)
Valid data URLs follow this format:
data:[<mediatype>][;base64],<data>
Examples:
data:image/png;base64,iVBORw0KGgo...
data:application/pdf;base64,JVBERi0x...
data:text/plain;base64,SGVsbG8gV29...
The ServerFile type automatically provides file content in the correct data URL format when using the useFileStorage composable on the frontend.
Use Cases
- File validation - Check file type before storage
- Custom storage - Implement your own storage logic
- File processing - Process files before storing (resize, convert, etc.)
- Metadata extraction - Get file information without storing
- Content analysis - Analyze file content for security or quality
- Format conversion - Convert files to different formats
- Multiple destinations - Store the same file in multiple locations
- Virus scanning - Scan file content before storage
The function decodes the entire file into memory as a Buffer. For very large files, this could consume significant memory. Consider streaming approaches for files larger than 10-20MB.
See Also
Source
View the source code on GitHub.