UNPKG

@bigfishtv/cockpit

Version:

156 lines (141 loc) 5.66 kB
/** * File Utilities * @module Utilities/fileUtils */ import pluploadSettings from '../config/pluploadSettings' import filesizeParser from 'filesize-parser' import filesize from 'file-size' import { notifyFailure } from '../actions/notifications' let store = null const maxSize = filesizeParser(pluploadSettings.max_file_size) /** * Makes a reference to redux store for notification dispatches * @param {Object} store */ export function init(_store) { store = _store } /** * Filters an of files based on validation props provided * @param {Array} files - Array of files * @param {Object} props - Uploader props: multiple, maxFiles, files, subject * @return {Array} - Returns filtered array of files depending on max files and filesize limits, or empty array. Will dispatch notifications via store */ export function validateFiles(files, props = {}) { const maxFiles = props.multiple ? (props.maxFiles ? props.maxFiles : 9999) : 1 const currentFiles = props.files || [] const fileTypeStore = store && store.getState().fileTypes const subject = props.subject const extensions = subject && fileTypeStore && subject in fileTypeStore ? fileTypeStore[subject] : null if (maxFiles && currentFiles.length + files.length > maxFiles) { const remaining = maxFiles - currentFiles.length if (store) store.dispatch(notifyFailure('Too many files! (' + maxFiles + ' allowed, ' + remaining + ' remaining)')) return [] } const maxBytes = (store && store.getState().maximumUploadSize) || maxSize return files.filter(file => { if (extensions && !isValidExtension(file, extensions)) { const extension = getExtension(file.name) if (store) store.dispatch(notifyFailure('".' + extension + '" is an invalid ' + (subject || 'file') + ' type!')) } else if (file.size > maxBytes) { const sizeReadable = filesize(file.size).human('si') const maxSizeReadable = filesize(maxBytes).human('si') if (store) store.dispatch( notifyFailure('"' + file.name + '" is too big (' + sizeReadable + '), limit is ' + maxSizeReadable) ) } else { return true } return false }) } /** * Takes filename and returns file extension * @param {String} filename - File name (can include path) * @return {String} - Returns extension */ export function getExtension(filename) { if (typeof filename !== 'string' || filename.indexOf('.') < 0) return false return filename.substring(filename.lastIndexOf('.') + 1, filename.length).toLowerCase() } /** * Is basically a glorified inArray function... * @param {Object} file - File object containing 'name' key * @param {Array} extensions - Array of valid file extensions * @return {Boolean} - Returns true or false if file's extension is valid */ export function isValidExtension(file, extensions) { if (typeof file !== 'object' || !file.name || !(extensions instanceof Array)) return false const extension = getExtension(file.name) return extension && extensions.indexOf(extension) >= 0 } /** * Cherry picks bits of data from native file object and returns new object * @param {Object} file - Native file object, e.g. from drop zone * @return {Object} - Returns object with data extracted from native file */ export function createFileObjectFromNative(file) { return { name: file.name, type: file.type, extension: getExtension(file.name), lastModified: file.lastModified, lastModifiedDate: file.lastModifiedDate, size: file.size, } } /** * Takes a native file object and a callback. It loads the file via FileReader and once read sends data url back via callback * @param {Object} file - Native file object * @param {Function} callback - Callback function, called with 1 argument - the image's data url */ export function extractDataUrlFromNative(file, callback = () => false) { const img = new FileReader() img.onload = function(e) { callback(this.result) } img.readAsDataURL(file) } /** * Tank specific function for getting a generated image url based on size preset and extension * @param {Object} file - Image object, containing keys: filename, * @param {String} size - Image size preset - defined in tank, defaults to 'cockpit-small' * @param {String} extension - Not required, used to specify extension, defaults to original file extension * @param {Boolean} getOriginal - Whether or not to fetch pre-edited image * @return {String} - Returns url string */ export function getImageUrl(file, size = 'cockpit-small', extension = null, getOriginal = false) { if (typeof file != 'object' || file instanceof Array || !file.filename || typeof size != 'string') return false const dot = file.filename.lastIndexOf('.') if (!file.slug) file.slug = file.filename.substr(0, dot) if (!file.extension) file.extension = file.filename.substr(dot + 1, file.filename.length) if (file.extension === 'svg') return getAssetUrl(file) if (file.extension === 'pdf' && !extension) extension = 'png' const originalStr = getOriginal ? 'original/' : '' const url = '/generated/' + originalStr + size + '/' + file.slug + '.' + (extension ? extension : file.extension ? file.extension : 'jpg') return url } /** * Takes file object and returns original upload url * @param {Object} file - File object, containing keys: filename * @return {String} - Returns url to original upload */ export function getAssetUrl(file) { if ( file instanceof Array || (typeof file != 'object' && typeof file != 'string') || (typeof file == 'object' && !file.filename) ) return false const filename = typeof file == 'string' ? file : file.filename const url = '/uploads/' + filename return url }