UNPKG

adonis-framework

Version:

Adonis framework makes it easy for you to write webapps with less code

313 lines (285 loc) 5.8 kB
'use strict' /** * adonis-framework * * (c) Harminder Virk <virk@adonisjs.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const path = require('path') const fs = require('co-fs-extra') const bytes = require('bytes') const CE = require('../Exceptions') /** * Used by request object internally to manage file uploads. * * @class * * @alias Request.file */ class File { constructor (formidableObject, options) { options = options || {} this.file = formidableObject this.file.deleted = false this.file.error = null this.file.fileName = '' this.file.maxSize = options.maxSize ? bytes(options.maxSize) : null this.file.allowedExtensions = options.allowedExtensions || [] this.file.filePath = '' } /** * sets error on the file instance and clears * the file name and path * * @param {String} error * * @private */ _setError (error) { this.file.error = error this.file.fileName = '' this.file.filePath = '' } /** * sets filePath and name after the move * and clears the error. * * @param {String} fileName * @param {String} filePath * * @private */ _setUploadedFile (fileName, filePath) { this.file.error = null this.file.fileName = fileName this.file.filePath = filePath } /** * sets file size exceeds error * * @private */ _setFileSizeExceedsError () { this._setError(`Uploaded file size ${bytes(this.clientSize())} exceeds the limit of ${bytes(this.file.maxSize)}`) } /** * sets file size extension error * * @private */ _setFileExtensionError () { this._setError(`Uploaded file extension ${this.extension()} is not valid`) } /** * validates the file size * * @return {Boolean} * * @private */ _underAllowedSize () { return !this.file.maxSize || (this.clientSize() <= this.file.maxSize) } /** * returns whether file has one of the defined extension * or not. * * @return {Boolean} [description] * * @private */ _hasValidExtension () { return !this.file.allowedExtensions.length || this.file.allowedExtensions.indexOf(this.extension()) > -1 } /** * a method to validate a given file. * * @return {Boolean} */ validate () { if (!this._hasValidExtension()) { this._setFileExtensionError() return false } else if (!this._underAllowedSize()) { this._setFileSizeExceedsError() return false } return true } /** * validates the file size and move it to the destination * * @param {String} fileName * @param {String} completePath * * @private */ * _validateAndMove (fileName, completePath) { if (!this.validate()) { return } try { yield fs.move(this.tmpPath(), completePath) this._setUploadedFile(fileName, completePath) } catch (error) { this._setError(error) } } /** * moves uploaded file from tmpPath to a given location. This is * an async function. * * @param {String} toPath * @param {String} name * * @example * yield file.move() * * @public */ move (toPath, name) { if (this.file.deleted === true) { throw CE.RuntimeException.fileDeleted() } name = name || this.clientName() const uploadingFileName = `${toPath}/${name}` return this._validateAndMove(name, uploadingFileName) } /** * Deletes a file * * @return {Boolean} * * @example * yield file.delete() * * @public */ delete () { return new Promise((resolve, reject) => { if (this.file.deleted === true) { throw CE.RuntimeException.fileDeleted() } let path = this.uploadPath() || this.tmpPath() fs.unlink(path, (err) => { if (err) return reject(err) resolve(true) this.file.deleted = true }) }) } /** * returns name of the uploaded file inside tmpPath. * * @return {String} * * @public */ clientName () { return this.file.name } /** * returns file mime type detected from original uploaded file. * * @return {String} * * @public */ mimeType () { return this.file.type } /** * returns file extension from original uploaded file. * * @return {String} * * @public */ extension () { return path.extname(this.clientName()).replace('.', '') } /** * returns file size of original uploaded file. * * @return {String} * * @public */ clientSize () { return this.file.size } /** * returns temporary path of file. * * @return {String} * * @public */ tmpPath () { return this.file.path } /** * returns file name after moving file * * @return {String} * * @public */ uploadName () { return this.file.fileName } /** * returns complete uploadPath after moving file * * @return {String} * * @public */ uploadPath () { return this.file.filePath } /** * tells whether file exists on temporary path or not * * @return {Boolean} * * @public */ exists () { return this.tmpPath() && !this.file.deleted } /** * tells whether move operation was successful or not * * @return {Boolean} * * @public */ moved () { return !this.errors() } /** * returns errors caused while moving file * * @return {Object} * * @public */ errors () { return this.file.error } /** * returns the JSON representation of the * file instance. * * @return {Object} * * @public */ toJSON () { return this.file } } module.exports = File