Skip to content

Кодирование файлов в Node.js ​

Хелперы из hazehash/node читают файл изображения или буфер, декодируют его через sharp и кодируют пиксели. Это способ хешировать картинки на диске, не пиша самому код чтения пикселей.

ts
import { encodeFile, encodeFileToString, encodeFileDetailed } from 'hazehash/node'

sharp это необязательная peer-зависимость (0.33 или новее), поэтому установите её там, где используете эти хелперы:

bash
npm install --save-dev sharp

Без неё хелперы бросают PlaceholderError с кодом InvalidInput и сообщением, которое объясняет, как установить sharp. Точкам входа ядра он никогда не нужен.

Перед кодированием изображение переводится в sRGB и поворачивается по EXIF-ориентации, поэтому хеш соответствует тому, что показывает браузер. Все хелперы принимают одни и те же два аргумента:

pathOrBuffer ​

string | Uint8Array

Путь к файлу изображения или байты закодированного изображения (JPEG, PNG, WebP, AVIF, GIF и остальные форматы, которые читает sharp).

options ​

EncodeOptions · необязательно

Те же опции, что у encode(): budget, profile, alpha, analysisSize и weights.

Получение строки ​

encodeFileToString(pathOrBuffer, options?)

Promise<string>

Возвращает хеш в base64url.

ts
import { encodeFileToString } from 'hazehash/node'

const hash = await encodeFileToString('photo.jpg', { budget: 24 })
// "Ec7UwRWKIv5znmt3XYLUF5zBSYmAo0Wr"

Получение байтов ​

encodeFile(pathOrBuffer, options?)

Promise<Uint8Array>

Возвращает сырые байты хеша, для бинарной колонки.

ts
import { encodeFile } from 'hazehash/node'

const bytes = await encodeFile('photo.jpg')
bytes.length // 28

Получение размера вместе с хешем ​

encodeFileDetailed(pathOrBuffer, options?)

Promise<EncodedFile>

Возвращает байты, строку и размер изображения в пикселях в том виде, как оно показывается, то есть после поворота по EXIF. Это функция, на которой построена команда hazehash encode, и способ сохранить настоящие размеры рядом с хешем.

ts
import { encodeFileDetailed } from 'hazehash/node'

const { hash, bytes, width, height } = await encodeFileDetailed('photo.jpg')
// hash: "Ed7UwRWKKv5znm6a7sC1tziHDNpMuCikxrYpIg", width: 1280, height: 959

Результат имеет такую форму:

ts
interface EncodedFile {
  bytes: Uint8Array // байты хеша
  hash: string // хеш в base64url
  width: number // размер в пикселях, как показывается
  height: number
}

Хеширование папки ​

Хелперы хешируют одну картинку за вызов. Для папки обойдите файлы циклом; сам энкодер занимает несколько миллисекунд, так что время уходит на декодирование изображения:

ts
import { readdir, writeFile } from 'node:fs/promises'
import { extname, join } from 'node:path'
import { encodeFileToString } from 'hazehash/node'

const dir = './images'
const hashes: Record<string, string> = {}

for (const name of await readdir(dir)) {
  if (['.jpg', '.jpeg', '.png', '.webp'].includes(extname(name).toLowerCase())) {
    hashes[name] = await encodeFileToString(join(dir, name), { budget: 24 })
  }
}

await writeFile('hashes.json', JSON.stringify(hashes, null, 2))

Для разовой задачи то же делает команда без кода: npx hazehash encode ./images -f json -o hashes.json. В Nuxt модуль генерирует и кэширует хеши при сборке.