浏览代码

add getFileType, getArrayBuffer and isPreviewReady methods for detecting file types

Artur Paikin 7 年之前
父节点
当前提交
62c15258dd
共有 5 个文件被更改,包括 99 次插入75 次删除
  1. 5 0
      package-lock.json
  2. 1 0
      package.json
  3. 51 57
      src/core/Core.js
  4. 42 7
      src/core/Utils.js
  5. 0 11
      src/plugins/Dashboard/FileCard.js

+ 5 - 0
package-lock.json

@@ -2186,6 +2186,11 @@
       "integrity": "sha1-/a2ZnLf6REODULUUx4+TWzBuk+M=",
       "integrity": "sha1-/a2ZnLf6REODULUUx4+TWzBuk+M=",
       "dev": true
       "dev": true
     },
     },
+    "file-type": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.1.1.tgz",
+      "integrity": "sha1-s/9Bu7uYXi/l9FJiNMsDHHAe5c0="
+    },
     "filename-regex": {
     "filename-regex": {
       "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz",
       "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz",
       "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=",
       "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=",

+ 1 - 0
package.json

@@ -76,6 +76,7 @@
   "dependencies": {
   "dependencies": {
     "drag-drop": "2.13.2",
     "drag-drop": "2.13.2",
     "es6-promise": "3.2.1",
     "es6-promise": "3.2.1",
+    "file-type": "^5.1.1",
     "lodash.throttle": "4.1.1",
     "lodash.throttle": "4.1.1",
     "namespace-emitter": "1.0.0",
     "namespace-emitter": "1.0.0",
     "nanoraf": "3.0.1",
     "nanoraf": "3.0.1",

+ 51 - 57
src/core/Core.js

@@ -147,56 +147,66 @@ class Uppy {
     const updatedFiles = Object.assign({}, this.state.files)
     const updatedFiles = Object.assign({}, this.state.files)
 
 
     const fileName = file.name || 'noname'
     const fileName = file.name || 'noname'
-    const fileType = Utils.getFileType(file)
-    const fileTypeGeneral = fileType[0]
-    const fileTypeSpecific = fileType[1]
     const fileExtension = Utils.getFileNameAndExtension(fileName)[1]
     const fileExtension = Utils.getFileNameAndExtension(fileName)[1]
     const isRemote = file.isRemote || false
     const isRemote = file.isRemote || false
 
 
     const fileID = Utils.generateFileID(fileName)
     const fileID = Utils.generateFileID(fileName)
 
 
-    const newFile = {
-      source: file.source || '',
-      id: fileID,
-      name: fileName,
-      extension: fileExtension || '',
-      meta: {
-        name: fileName
-      },
-      type: {
-        general: fileTypeGeneral,
-        specific: fileTypeSpecific
-      },
-      data: file.data,
-      progress: {
-        percentage: 0,
-        uploadComplete: false,
-        uploadStarted: false
-      },
-      size: file.data.size || 'N/A',
-      isRemote: isRemote,
-      remote: file.remote || '',
-      preview: file.preview
-    }
+    // const fileType = Utils.getFileType(file)
+    // const fileTypeGeneral = fileType[0]
+    // const fileTypeSpecific = fileType[1]
+
+    Utils.getFileType(file).then((fileType) => {
+      const fileTypeGeneral = fileType[0]
+      const fileTypeSpecific = fileType[1]
+
+      const newFile = {
+        source: file.source || '',
+        id: fileID,
+        name: fileName,
+        extension: fileExtension || '',
+        meta: {
+          name: fileName
+        },
+        type: {
+          general: fileTypeGeneral,
+          specific: fileTypeSpecific
+        },
+        data: file.data,
+        progress: {
+          percentage: 0,
+          uploadComplete: false,
+          uploadStarted: false
+        },
+        size: file.data.size || 'N/A',
+        isRemote: isRemote,
+        remote: file.remote || '',
+        preview: file.preview
+      }
 
 
-    if (fileTypeGeneral === 'image' && !isRemote) {
-      newFile.preview = Utils.getThumbnail(file)
-    }
+      if (Utils.isPreviewReady(fileTypeSpecific) && !isRemote) {
+        newFile.preview = Utils.getThumbnail(file)
+      }
 
 
-    updatedFiles[fileID] = newFile
-    this.setState({files: updatedFiles})
+      updatedFiles[fileID] = newFile
+      this.setState({files: updatedFiles})
 
 
-    this.bus.emit('file-added', fileID)
-    this.log(`Added file: ${fileName}, ${fileID}, mime type: ${fileType}`)
+      this.bus.emit('file-added', fileID)
+      this.log(`Added file: ${fileName}, ${fileID}, mime type: ${fileType}`)
 
 
-    if (this.opts.autoProceed && !this.scheduledAutoProceed) {
-      this.scheduledAutoProceed = setTimeout(() => {
-        this.scheduledAutoProceed = null
-        this.upload().catch((err) => {
-          console.error(err.stack || err.message)
-        })
-      }, 4)
-    }
+      if (!fileType) {
+        console.log('well, yeah, file type is fucking empty')
+      }
+
+      if (this.opts.autoProceed && !this.scheduledAutoProceed) {
+        this.scheduledAutoProceed = setTimeout(() => {
+          this.scheduledAutoProceed = null
+          this.upload().catch((err) => {
+            console.error(err.stack || err.message)
+          })
+        }, 4)
+      }
+    })
   }
   }
 
 
   removeFile (fileID) {
   removeFile (fileID) {
@@ -254,14 +264,6 @@ class Uppy {
     this.setState({
     this.setState({
       totalProgress: totalProgress
       totalProgress: totalProgress
     })
     })
-
-    // if (totalProgress === 100) {
-    //   const completeFiles = Object.keys(updatedFiles).filter((file) => {
-    //     // this should be `uploadComplete`
-    //     return updatedFiles[file].progress.percentage === 100
-    //   })
-    //   this.emit('core:success', completeFiles.length)
-    // }
   }
   }
 
 
   /**
   /**
@@ -553,14 +555,6 @@ class Uppy {
     return this.socket
     return this.socket
   }
   }
 
 
-  // installAll () {
-  //   Object.keys(this.plugins).forEach((pluginType) => {
-  //     this.plugins[pluginType].forEach((plugin) => {
-  //       plugin.install(this)
-  //     })
-  //   })
-  // }
-
 /**
 /**
  * Initializes actions, installs all plugins (by iterating on them and calling `install`), sets options
  * Initializes actions, installs all plugins (by iterating on them and calling `install`), sets options
  *
  *

+ 42 - 7
src/core/Utils.js

@@ -1,6 +1,5 @@
 const throttle = require('lodash.throttle')
 const throttle = require('lodash.throttle')
-// import mime from 'mime-types'
-// import pica from 'pica'
+const fileType = require('file-type')
 
 
 /**
 /**
  * A collection of small utility functions that help with dom manipulation, adding listeners,
  * A collection of small utility functions that help with dom manipulation, adding listeners,
@@ -147,8 +146,46 @@ function runPromiseSequence (functions, ...args) {
 //   return (!f && 'not a function') || (s && s[1] || 'anonymous')
 //   return (!f && 'not a function') || (s && s[1] || 'anonymous')
 // }
 // }
 
 
+function isPreviewReady (fileTypeSpecific) {
+  // list of images that browsers can preview
+  if (/^(jpeg|gif|png|svg|bmp)$/.test(fileTypeSpecific)) {
+    return true
+  }
+  return false
+}
+
+function getArrayBuffer (file) {
+  return new Promise(function (resolve, reject) {
+    var reader = new FileReader()
+    reader.addEventListener('load', function (e) {
+      // e.target.result is an ArrayBuffer
+      var arr = new Uint8Array(e.target.result)
+      resolve(arr)
+    })
+    reader.addEventListener('error', function (err) {
+      console.error('FileReader error' + err)
+      reject(err)
+    })
+    const chunk = file.data.slice(0, 4100)
+    reader.readAsArrayBuffer(chunk)
+  })
+}
+
 function getFileType (file) {
 function getFileType (file) {
-  return file.type ? file.type.split('/') : ['', '']
+  if (file.type) {
+    return Promise.resolve(file.type.split('/'))
+  }
+
+  return getArrayBuffer(file).then((buffer) => {
+    const type = fileType(buffer)
+    if (type && type.mime) {
+      return type.mime.split('/')
+    }
+    return ['', '']
+  })
+
+  // return mime.lookup(file.name)
+  // return file.type ? file.type.split('/') : ['', '']
   // return mime.lookup(file.name)
   // return mime.lookup(file.name)
 }
 }
 
 
@@ -403,8 +440,6 @@ module.exports = {
   every,
   every,
   flatten,
   flatten,
   groupBy,
   groupBy,
-  // $,
-  // $$,
   extend,
   extend,
   runPromiseSequence,
   runPromiseSequence,
   supportsMediaRecorder,
   supportsMediaRecorder,
@@ -413,6 +448,8 @@ module.exports = {
   truncateString,
   truncateString,
   getFileTypeExtension,
   getFileTypeExtension,
   getFileType,
   getFileType,
+  getArrayBuffer,
+  isPreviewReady,
   getThumbnail,
   getThumbnail,
   secondsToTime,
   secondsToTime,
   dataURItoBlob,
   dataURItoBlob,
@@ -420,8 +457,6 @@ module.exports = {
   getSpeed,
   getSpeed,
   getBytesRemaining,
   getBytesRemaining,
   getETA,
   getETA,
-  // makeWorker,
-  // makeCachingFunction,
   copyToClipboard,
   copyToClipboard,
   prettyETA,
   prettyETA,
   findDOMElement,
   findDOMElement,

+ 0 - 11
src/plugins/Dashboard/FileCard.js

@@ -2,17 +2,6 @@ const html = require('yo-yo')
 const getFileTypeIcon = require('./getFileTypeIcon')
 const getFileTypeIcon = require('./getFileTypeIcon')
 const { checkIcon } = require('./icons')
 const { checkIcon } = require('./icons')
 
 
-// function getIconByMime (fileTypeGeneral) {
-//   switch (fileTypeGeneral) {
-//     case 'text':
-//       return iconText()
-//     case 'audio':
-//       return iconAudio()
-//     default:
-//       return iconFile()
-//   }
-// }
-
 module.exports = function fileCard (props) {
 module.exports = function fileCard (props) {
   const file = props.fileCardFor ? props.files[props.fileCardFor] : false
   const file = props.fileCardFor ? props.files[props.fileCardFor] : false
   const meta = {}
   const meta = {}