Better file type detection

This commit is contained in:
Artur Paikin 2016-07-26 19:34:59 -04:00
parent cbda447d5a
commit 024ebfa192
4 changed files with 124 additions and 57 deletions

View file

@ -95,15 +95,18 @@ export default class Core {
addFile (file) {
const updatedFiles = Object.assign({}, this.state.files)
const fileType = file.type.split('/')
const fileType = Utils.getFileType(file) ? Utils.getFileType(file).split('/') : ['', '']
const fileTypeGeneral = fileType[0]
const fileTypeSpecific = fileType[1]
const fileExtension = Utils.getFileNameAndExtension(file.name)[1]
const fileID = Utils.generateFileID(file.name)
updatedFiles[fileID] = {
source: file.source || '',
id: fileID,
name: file.name,
extension: fileExtension,
type: {
general: fileTypeGeneral,
specific: fileTypeSpecific
@ -119,8 +122,10 @@ export default class Core {
this.setState({files: updatedFiles})
if (fileTypeGeneral === 'image') {
// this.addImgPreviewToFile(updatedFiles[fileID])
Utils.readImage(updatedFiles[fileID].data, (imgEl) => {
Utils.readImage(updatedFiles[fileID].data, (err, imgEl) => {
if (err) {
return this.log(err)
}
const newImageWidth = 200
const newImageHeight = Utils.getProportionalImageHeight(imgEl, newImageWidth)
const resizedImgSrc = Utils.resizeImage(imgEl, newImageWidth, newImageHeight)
@ -188,8 +193,6 @@ export default class Core {
const updatedFiles = Object.assign({}, this.state.files)
updatedFiles[file.id] = file
this.setState({files: updatedFiles})
// this.log(this.state.uploadedFiles)
// this.emitter.emit('file-remove', file.id)
})
}
@ -314,27 +317,6 @@ export default class Core {
})
return
// Each Plugin can have `run` and/or `install` methods.
// `install` adds event listeners and does some non-blocking work, useful for `progressindicator`,
// `run` waits for the previous step to finish (user selects files) before proceeding
// ['install', 'run'].forEach((method) => {
// // First we select only plugins of current type,
// // then create an array of runType methods of this plugins
// const typeMethods = this.types.filter((type) => this.plugins[type])
// .map((type) => this.runType.bind(this, type, method))
// // Run waterfall of typeMethods
// return Utils.promiseWaterfall(typeMethods)
// .then((result) => {
// // If results are empty, don't log upload results. Hasn't run yet.
// if (result[0] !== undefined) {
// this.log(result)
// this.log('Upload result -> success!')
// return result
// }
// })
// .catch((error) => this.log('Upload result -> failed:', error))
// })
}
initSocket (opts) {

View file

@ -1,3 +1,5 @@
import mime from 'mime-types'
/**
* A collection of small utility functions that help with dom manipulation, adding listeners,
* promises and other good things.
@ -35,10 +37,44 @@ function isTouchDevice () {
};
/**
* `querySelectorAll` that returns a normal array instead of fileList
* Shorter and fast way to select multiple nodes in the DOM
* @param { String|Array } selector - DOM selector or nodes list
* @param { Object } ctx - DOM node where the targets of our search will is located
* @returns { Object } dom nodes found
*/
function qsa (selector, context) {
return Array.prototype.slice.call((context || document).querySelectorAll(selector) || [])
export function $$ (selector, ctx) {
var els
if (typeof selector === 'string') {
els = (ctx || document).querySelectorAll(selector)
} else {
els = selector
return Array.prototype.slice.call(els)
}
}
/**
* Shorter and fast way to select a single node in the DOM
* @param { String } selector - unique dom selector
* @param { Object } ctx - DOM node where the target of our search will is located
* @returns { Object } dom node found
*/
export function $ (selector, ctx) {
return (ctx || document).querySelector(selector)
}
// returns [fileName, fileExt]
function getFileNameAndExtension (fullFileName) {
var re = /(?:\.([^.]+))?$/
var fileExt = re.exec(fullFileName)[1]
var fileName = fullFileName.replace('.' + fileExt, '')
return [fileName, fileExt]
}
function truncateString (string, length) {
if (string.length > length) {
return string.substring(0, length) + '…'
}
return string
}
/**
@ -131,13 +167,16 @@ function readImage (imgObject, cb) {
reader.addEventListener('load', function (ev) {
var imgSrcBase64 = ev.target.result
var img = new Image()
img.onload = function () {
return cb(img)
}
img.addEventListener('load', function () {
return cb(null, img)
})
img.addEventListener('error', function (err) {
return cb(err)
})
img.src = imgSrcBase64
})
reader.addEventListener('error', function (err) {
console.log('FileReader error' + err)
console.log('FileReader error ' + err)
})
reader.readAsDataURL(imgObject)
}
@ -148,6 +187,19 @@ function getProportionalImageHeight (img, newWidth) {
return newHeight
}
function getFileType (file) {
// if (file.type) {
// const fileType = file.type.split('/')
// return fileType
// }
// const fileExtension = getFileNameAndExtension(file.name)[1]
// return fileExtension
if (file.type) {
return file.type
}
return mime.lookup(file.name)
}
/**
* Resizes an image to specified width and height, using canvas
* See https://davidwalsh.name/resize-image-canvas
@ -167,11 +219,12 @@ function resizeImage (img, width, height) {
canvas.height = height
// draw source image into the off-screen canvas:
// ctx.clearRect(0, 0, width, height)
ctx.drawImage(img, 0, 0, width, height)
// encode image to data-uri with base64 version of compressed image
// canvas.toDataURL('image/jpeg', quality); // quality = [0.0, 1.0]
return canvas.toDataURL()
return canvas.toDataURL('image/jpeg', 0.7)
}
export default {
@ -182,10 +235,14 @@ export default {
every,
flatten,
groupBy,
qsa,
$,
$$,
extend,
readImage,
resizeImage,
getProportionalImageHeight,
isTouchDevice
isTouchDevice,
getFileNameAndExtension,
truncateString,
getFileType
}

View file

@ -1,31 +1,62 @@
import html from 'yo-yo'
import { fileIcon, checkIcon, removeIcon } from './icons'
import Utils from '../../core/Utils'
import { checkIcon, removeIcon, iconText, iconFile, iconAudio } from './icons'
function getIconByMime (fileTypeGeneral) {
switch (fileTypeGeneral) {
case 'text':
return iconText()
case 'audio':
return iconAudio()
default:
return iconFile()
}
}
export default function fileItem (bus, file) {
const isUploaded = file.progress === 100
const uploadInProgress = file.progress > 0 && file.progress < 100
const remove = (ev) => {
bus.emit('file-remove', file.id)
function remove (ev) {
const el = document.querySelector(`#${file.id}`)
el.classList.add('UppyAnimation-zoomOutLeft')
// this seems to be working in latest Chrome, Firefox and Safari,
// but might not be 100% cross-browser, needs testing
// https://davidwalsh.name/css-animation-callback
el.addEventListener('animationend', () => {
bus.emit('file-remove', file.id)
})
// bus.emit('file-remove', file.id)
}
const truncatedFileName = Utils.truncateString(file.name, 30)
// <h5 class="UppyDashboardItem-previewType">${file.extension ? '.' + file.extension : '?'}</h5>
return html`<li class="UppyDashboardItem"
id="${file.id}"
title="${file.name}">
<div class="UppyDashboardItem-icon">
${file.type.general === 'image' ? file.previewEl : fileIcon(file.type)}
</div>
<h4 class="UppyDashboardItem-name">
${file.uploadURL
? html`<a href="${file.uploadURL}" target="_blank">${file.name}</a>`
: html`<span>${file.name}</span>`
}
<br>
</h4>
<div class="UppyDashboardItem-status">
<div class="UppyDashboardItem-statusSize">${file.totalSize}</div>
${uploadInProgress ? 'Uploading… ' + file.progress + '%' : ''}
${isUploaded ? 'Completed' : ''}
<div class="UppyDashboardItem-preview">
${file.previewEl
? file.previewEl
: html`<div class="UppyDashboardItem-previewIcon">${getIconByMime(file.type.general)}</div>`
}
<div class="UppyDashboardItem-progress ${uploadInProgress ? 'is-active' : ''}">
<div class="UppyDashboardItem-progressNum">${file.progress}%</div>
<div class="UppyDashboardItem-progressInner" style="width: ${file.progress}%"></div>
</div>
</div>
<div class="UppyDashboardItem-info">
<h4 class="UppyDashboardItem-name">
${file.uploadURL
? html`<a href="${file.uploadURL}" target="_blank">${truncatedFileName}</a>`
: truncatedFileName
}
</h4>
<div class="UppyDashboardItem-status">
<span class="UppyDashboardItem-statusSize">${file.totalSize}</span>
</div>
</div>
<div class="UppyDashboardItem-action">
${isUploaded
@ -37,8 +68,5 @@ export default function fileItem (bus, file) {
</button>`
}
</div>
<div class="UppyDashboardItem-progress ${uploadInProgress ? 'is-active' : ''}">
<div class="UppyDashboardItem-progressInner" style="width: ${file.progress}%"></div>
</div>
</li>`
}

View file

@ -338,7 +338,7 @@ export default class Modal extends Plugin {
<div class="UppyModalContent-bar">
<h2 class="UppyModalContent-title">Import From ${target.name}</h2>
<button class="UppyModalContent-back"
onclick=${this.hideAllPanels}>Back</button>
onclick=${this.hideAllPanels}>Done</button>
</div>
${target.render(state)}
</div>`