Skip to content

Instantly share code, notes, and snippets.

@reggi
Created November 26, 2023 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reggi/cf8a5b3ecbd6bbff4e38c27c65110233 to your computer and use it in GitHub Desktop.
Save reggi/cf8a5b3ecbd6bbff4e38c27c65110233 to your computer and use it in GitHub Desktop.
---
import { createHash } from 'node:crypto';
import fs from 'node:fs/promises';
import path from 'node:path';
type Props = {
src: string,
alt?: string,
class?: string,
}
const { src, alt, class: className } = Astro.props
async function fileExistsByBasename(dirPath: string, baseName: string): Promise<boolean> {
try {
const files = await fs.readdir(dirPath);
return files.some(file => path.basename(file, path.extname(file)) === baseName);
} catch {
return false;
}
}
function getImageExtension(mimeType: string): string | null {
const mimeToExtension: { [key: string]: string } = {
'image/jpeg': '.jpg',
'image/png': '.png',
'image/gif': '.gif',
'image/webp': '.webp',
'image/svg+xml': '.svg'
}
return mimeToExtension[mimeType] || null;
}
const dir = './public/downloads';
const name = createHash('md5').update(src).digest('hex').substring(0, 16)
let ext = path.extname(src)
let filepath = path.join(dir, `${name}${ext}`);
const exists = await fileExistsByBasename(dir, filepath);
if (!exists) {
const response = await fetch(src);
const contentType = response.headers.get('content-type')
if (ext === '' && contentType) {
const matched = getImageExtension(contentType)
if (matched) {
ext = matched
filepath = path.join(dir, `${name}${ext}`);
}
}
if (!response.ok) {
throw new Error(`Failed to fetch ${src}: ${response.statusText}`);
}
const arrayBuffer = await response.arrayBuffer()
const buffer = Buffer.from(arrayBuffer);
await fs.writeFile(filepath, buffer);
}
---
<img src={path.join('./downloads', `${name}${ext}`)} alt={alt} class={className} />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment