DockerERTFF/lib/modules/upload.js

118 lines
4.7 KiB
JavaScript

const fs = require('fs-extra');
const debug = require('debug')('server-connect:upload');
const { join, basename, extname } = require('path');
const { toAppPath, toSystemPath, toSiteUrl, parseTemplate, getUniqFile } = require('../core/path');
const diacritics = require('../core/diacritics');
module.exports = {
upload: async function(options) {
let self = this;
let fields = this.parse(options.fields || this.parse('{{$_POST}}'));
let path = this.parseOptional(options.path, 'string', '/uploads');
let overwrite = this.parseOptional(options.overwrite, 'boolean', false);
let createPath = this.parseOptional(options.createPath, 'boolean', true);
let throwErrors = this.parseOptional(options.throwErrors, 'boolean', false);
let template = typeof options.template == 'string' ? options.template : false; //this.parseOptional(options.template, 'string', '');
let replaceSpace = this.parseOptional(options.replaceSpace, 'boolean', false);
let asciiOnly = this.parseOptional(options.asciiOnly, 'boolean', false);
let replaceDiacritics = this.parseOptional(options.replaceDiacritics, 'boolean', false);
if (throwErrors) {
for (let field in this.req.files) {
if (Array.isArray(this.req.files[field])) {
for (let file of this.req.files[field]) {
if (file.truncated) {
throw new Error('Some files failed to upload.');
}
}
} else {
let file = this.req.files[field];
if (file.truncated) {
throw new Error('Some files failed to upload.');
}
}
}
}
path = toSystemPath(path);
if (!fs.existsSync(path)) {
if (createPath) {
await fs.ensureDir(path);
} else {
throw new Error(`Upload path doesn't exist.`);
}
}
let files = this.req.files;
let uploaded = [];
if (files) {
await processFields(fields);
}
return typeof fields == 'string' ? (uploaded.length ? uploaded[0] : null) : uploaded;
async function processFields(fields) {
debug('Process fields: %O', fields);
if (typeof fields == 'object') {
for (let i in fields) {
await processFields(fields[i]);
}
} else if (typeof fields == 'string' && files[fields]) {
let processing = files[fields];
if (!Array.isArray(processing)) processing = [processing];
for (let file of processing) {
debug('Processing file: %O', file);
if (!file.processed) {
let name = file.name.replace(/[\x00-\x1f\x7f!%&#@$*()?:,;"'<>^`|+={}\[\]\\\/]/g, '');
if (replaceSpace) name = name.replace(/\s+/g, '_');
if (replaceDiacritics) name = diacritics.replace(name);
if (asciiOnly) name = name.replace(/[^\x00-\x7e]/g, '');
let filepath = join(path, name);
if (template) {
let _template = self.parse(template, self.scope.create({
file: basename(filepath),
name: basename(filepath, extname(filepath)),
ext: extname(filepath)
}));
filepath = parseTemplate(filepath, _template);
}
if (fs.existsSync(filepath)) {
if (overwrite) {
await fs.unlink(filepath);
} else {
filepath = getUniqFile(filepath);
}
}
await file.mv(filepath);
uploaded.push({
name: basename(filepath),
path: toAppPath(filepath),
url: toSiteUrl(filepath),
type: file.mimetype,
size: file.size
});
file.processed = true;
}
}
}
return uploaded;
}
}
};