import config from 'config'; import path from 'path'; import fs from 'fs/promises'; import mime from 'mime'; import crypto from 'crypto'; import { fileTypeFromBuffer } from 'file-type'; import sharp from 'sharp'; import { HttpError } from '#src/errors.js'; function hashFile(fileBuffer) { return crypto.createHash('sha256') .update(fileBuffer) .digest('hex'); } async function validateMimetype(file, fileBuffer) { const { mime } = await fileTypeFromBuffer(fileBuffer); if (mime !== file.mimetype) { throw new HttpError(`MIME type mismatch: ${file.mimetype} expected, ${mime} found`, 400); } } async function generateThumb(type, fileBuffer, hash, targetPath) { if (type === 'image') { await sharp(fileBuffer) .resize({ height: config.uploads.thumbHeight }) .jpeg({ quality: config.uploads.thumbQuality }) .toFile(path.join(targetPath, `${hash}_t.jpg`)); } } export async function uploadFiles(files, options) { console.log('FILES', files, options); await files.reduce(async (chain, file) => { await chain; const tempFilePath = path.join(config.uploads.path, 'temp', file.tempName); const fileBuffer = await fs.readFile(tempFilePath); const hash = hashFile(fileBuffer); await validateMimetype(file, fileBuffer); const targetPath = path.join(config.uploads.path, 'full', hash.slice(0, 2), hash.slice(2, 4)); const extension = mime.getExtension(file.mimetype); await fs.mkdir(targetPath, { recursive: true }); await Promise.all([ generateThumb(file.mimetype.split('/')[0], fileBuffer, hash, targetPath), fs.rename(path.join(config.uploads.path, 'temp', file.tempName), path.join(targetPath, `${hash}.${extension}`)), ]); }, Promise.resolve()); return files; } //# sourceMappingURL=files.js.map