118 lines
4.7 KiB
JavaScript
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;
|
|
}
|
|
|
|
}
|
|
|
|
}; |