mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-07-24 23:59:46 +02:00
* Transport controller and file model * Use randomBytes intead of pseudoRandomBytes * Cover all lines with tests * Update code style * Update code style * View for image block * Fix serving static files * Mkdir -p for uploads dirs * Add default secret param * Add image Tool * Update src/utils/objects.js Co-Authored-By: talyguryn <vitalik7tv@yandex.ru> * Use vars for image tool colors * Revert var * Remove --color-gray-border var * Update src/controllers/transport.js Co-Authored-By: talyguryn <vitalik7tv@yandex.ru> * Add mp4 support for Image Tool
119 lines
3.2 KiB
JavaScript
119 lines
3.2 KiB
JavaScript
const fileType = require('file-type');
|
|
const fetch = require('node-fetch');
|
|
const fs = require('fs');
|
|
const nodePath = require('path');
|
|
|
|
const Model = require('../models/file');
|
|
const { random16 } = require('../utils/crypto');
|
|
const { deepMerge } = require('../utils/objects');
|
|
const config = require('../../config');
|
|
|
|
/**
|
|
* @class Transport
|
|
* @classdesc Transport controller
|
|
*
|
|
* Allows to save files from client or fetch them by URL
|
|
*/
|
|
class Transport {
|
|
/**
|
|
* Saves file passed from client
|
|
* @param {object} multerData - file data from multer
|
|
* @param {string} multerData.originalname - original name of the file
|
|
* @param {string} multerData.filename - name of the uploaded file
|
|
* @param {string} multerData.path - path to the uploaded file
|
|
* @param {number} multerData.size - size of the uploaded file
|
|
* @param {string} multerData.mimetype - MIME type of the uploaded file
|
|
*
|
|
* @param {object} map - object that represents how should fields of File object should be mapped to response
|
|
* @return {Promise<FileData>}
|
|
*/
|
|
static async save(multerData, map) {
|
|
const { originalname: name, path, filename, size, mimetype } = multerData;
|
|
|
|
const file = new Model({ name, filename, path, size, mimetype });
|
|
|
|
await file.save();
|
|
|
|
let response = file.data;
|
|
|
|
if (map) {
|
|
response = Transport.composeResponse(file, map);
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
/**
|
|
* Fetches file by passed URL
|
|
* @param {string} url - URL of the file
|
|
* @param {object} map - object that represents how should fields of File object should be mapped to response
|
|
* @return {Promise<FileData>}
|
|
*/
|
|
static async fetch(url, map) {
|
|
const fetchedFile = await fetch(url);
|
|
const buffer = await fetchedFile.buffer();
|
|
const filename = await random16();
|
|
|
|
const type = fileType(buffer);
|
|
const ext = type ? type.ext : nodePath.extname(url).slice(1);
|
|
|
|
fs.writeFileSync(`${config.uploads}/${filename}.${ext}`, buffer);
|
|
|
|
const file = new Model({
|
|
name: url,
|
|
filename: `${filename}.${ext}`,
|
|
path: `${config.uploads}/${filename}.${ext}`,
|
|
size: buffer.length,
|
|
mimetype: type ? type.mime : fetchedFile.headers.get('content-type')
|
|
});
|
|
|
|
await file.save();
|
|
|
|
let response = file.data;
|
|
|
|
if (map) {
|
|
response = Transport.composeResponse(file, map);
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
/**
|
|
* Map fields of File object to response by provided map object
|
|
*
|
|
* @param {File} file
|
|
* @param {object} map - object that represents how should fields of File object should be mapped to response
|
|
*
|
|
*/
|
|
static composeResponse(file, map) {
|
|
const response = {};
|
|
const { data } = file;
|
|
|
|
Object.entries(map).forEach(([name, path]) => {
|
|
const fields = path.split(':');
|
|
|
|
if (fields.length > 1) {
|
|
let object = {};
|
|
let result = object;
|
|
|
|
fields.forEach((field, i) => {
|
|
if (i === fields.length - 1) {
|
|
object[field] = data[name];
|
|
return;
|
|
}
|
|
|
|
object[field] = {};
|
|
object = object[field];
|
|
});
|
|
|
|
deepMerge(response, result);
|
|
} else {
|
|
response[fields[0]] = data[name];
|
|
}
|
|
});
|
|
|
|
return response;
|
|
}
|
|
}
|
|
|
|
module.exports = Transport;
|