JSFiddle - React, Tailwind, and code Playground
by philfreo
HTML
<script src="http://underscorejs.org/underscore-min.js"></script>
<input type="file" id="myfile" />
JavaScript
var fileInput = document.getElementById('myfile');
fileInput.addEventListener('change', function(e) {
var file = e.currentTarget.files[0];
FileDetector.verifyFileType(file, ['mp3', 'wav'], function(isType) {
alert(!!isType);
});
});
var FileDetector = (function() {
// https://en.wikipedia.org/wiki/List_of_file_signatures
var fileSignatures = {
'mp3': [
// MPEG-1 Layer 3 file without an ID3 tag or with an ID3v1 tag (which's appended at the end of the file)
Uint8Array.from([0xFF, 0xFB]),
// MP3 file with an ID3v2 container
Uint8Array.from([0x49, 0x44, 0x33])
]
'wav': [
// Waveform Audio File Format
// Empty slots can be any byte. Can't look at only first 4 or else .avi files match
Uint8Array.from([0x52, 0x49, 0x46, 0x46, , , , , 0x57, 0x41, 0x56, 0x45])
]
};
/**
* Compare two Uint8Arrays. This function could be replaced by _.isEqual except
* for the fact that the signatures (e.g. wav files) can have wildcard slots.
* value, meaning that we should ignore those bytes.
* @param {Uint8Array} sig - pattern from fileSignatures
* @param {Uint8Array} actual - bytes from file (already sliced to match length of sig)
* @returns {boolean}
*/
var compareSignature = function(sig, actual) {
if (sig.length !== actual.length) return false;
for (var i = 0, l = sig.length, i < l; i++) {
if (sig[i] !== actual[i] && typeof sig[i] !== 'undefined') return false;
}
return true;
};
/**
* @param {Uint8Array} uint8
* @param {string} type
* @returns {boolean}
*/
var matchesFileType = function(uint8, type) {
return _.find(fileSignatures[type], function(sig) {
return compareSignature(sig, uint8.slice(0, sig.length));
});
};
return {
/**
* Detect, through file signature / mime sniffing detection, if a given File
* matches an expected type or types. The types supported are the keys in
* fileSignatures...