pubload/dist/files.js

46 lines
1.9 KiB
JavaScript

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