|
1 | | -/*! FileAPI 2.0.10 - BSD | git://github.com/mailru/FileAPI.git |
| 1 | +/*! FileAPI 2.0.11 - BSD | git://github.com/mailru/FileAPI.git |
2 | 2 | * FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF. |
3 | 3 | */ |
4 | 4 |
|
|
105 | 105 | document = window.document, |
106 | 106 | doctype = document.doctype || {}, |
107 | 107 | userAgent = window.navigator.userAgent, |
| 108 | +safari = /safari\//i.test(userAgent) && !/chrome\//i.test(userAgent), |
108 | 109 |
|
109 | 110 | // https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48 |
110 | 111 | apiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL), |
|
119 | 120 | jQuery = window.jQuery, |
120 | 121 |
|
121 | 122 | html5 = !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary))) |
122 | | -&& !(/safari\//i.test(userAgent) && !/chrome\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25 |
| 123 | +&& !(safari && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25 |
123 | 124 |
|
124 | 125 | cors = html5 && ('withCredentials' in (new XMLHttpRequest)), |
125 | 126 |
|
126 | 127 | chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice), |
127 | 128 |
|
| 129 | +normalize = ('' + ''.normalize).indexOf('[native code]') > 0, |
| 130 | + |
128 | 131 | // https://github.com/blueimp/JavaScript-Canvas-to-Blob |
129 | 132 | dataURLtoBlob = window.dataURLtoBlob, |
130 | 133 |
|
|
280 | 283 | * FileAPI (core object) |
281 | 284 | */ |
282 | 285 | api = { |
283 | | -version: '2.0.10', |
| 286 | +version: '2.0.11', |
284 | 287 |
|
285 | 288 | cors: false, |
286 | 289 | html5: true, |
|
795 | 798 | getDropFiles: function (evt, callback){ |
796 | 799 | var |
797 | 800 | files = [] |
| 801 | +, all = [] |
| 802 | +, items |
798 | 803 | , dataTransfer = _getDataTransfer(evt) |
799 | | -, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0]) |
800 | | -, queue = api.queue(function (){ callback(files); }) |
| 804 | +, transFiles = dataTransfer.files |
| 805 | +, transItems = dataTransfer.items |
| 806 | +, entrySupport = _isArray(transItems) && transItems[0] && _getAsEntry(transItems[0]) |
| 807 | +, queue = api.queue(function (){ callback(files, all); }) |
801 | 808 | ; |
802 | 809 |
|
803 | | -_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){ |
| 810 | +if( entrySupport ){ |
| 811 | +if( normalize && transFiles ){ |
| 812 | +var |
| 813 | +i = transFiles.length |
| 814 | +, file |
| 815 | +, entry |
| 816 | +; |
| 817 | + |
| 818 | +items = new Array(i); |
| 819 | +while( i-- ){ |
| 820 | +file = transFiles[i]; |
| 821 | + |
| 822 | +try { |
| 823 | +entry = _getAsEntry(transItems[i]); |
| 824 | +} |
| 825 | +catch( err ){ |
| 826 | +api.log('[err] getDropFiles: ', err); |
| 827 | +entry = null; |
| 828 | +} |
| 829 | + |
| 830 | +if( _isEntry(entry) ){ |
| 831 | +// OSX filesystems use Unicode Normalization Form D (NFD), |
| 832 | +// and entry.file(…) can't read the files with the same names |
| 833 | +if( entry.isDirectory || (entry.isFile && file.name == file.name.normalize('NFC')) ){ |
| 834 | +items[i] = entry; |
| 835 | +} |
| 836 | +else { |
| 837 | +items[i] = file; |
| 838 | +} |
| 839 | +} |
| 840 | +else { |
| 841 | +items[i] = file; |
| 842 | +} |
| 843 | +} |
| 844 | +} |
| 845 | +else { |
| 846 | +items = transItems; |
| 847 | +} |
| 848 | +} |
| 849 | +else { |
| 850 | +items = transFiles; |
| 851 | +} |
| 852 | + |
| 853 | +_each(items || [], function (item){ |
804 | 854 | queue.inc(); |
805 | 855 |
|
806 | 856 | try { |
807 | | -if( entrySupport ){ |
808 | | -_readEntryAsFiles(item, function (err, entryFiles){ |
| 857 | +if( entrySupport && _isEntry(item) ){ |
| 858 | +_readEntryAsFiles(item, function (err, entryFiles, allEntries){ |
809 | 859 | if( err ){ |
810 | 860 | api.log('[err] getDropFiles:', err); |
811 | 861 | } else { |
812 | 862 | files.push.apply(files, entryFiles); |
813 | 863 | } |
| 864 | +all.push.apply(all, allEntries); |
| 865 | + |
814 | 866 | queue.next(); |
815 | 867 | }); |
816 | 868 | } |
817 | 869 | else { |
818 | | -_isRegularFile(item, function (yes){ |
819 | | -yes && files.push(item); |
| 870 | +_isRegularFile(item, function (yes, err){ |
| 871 | +if( yes ){ |
| 872 | +files.push(item); |
| 873 | +} |
| 874 | +else { |
| 875 | +item.error = err; |
| 876 | +} |
| 877 | +all.push(item); |
| 878 | + |
820 | 879 | queue.next(); |
821 | 880 | }); |
822 | 881 | } |
|
1537 | 1596 |
|
1538 | 1597 | function _isRegularFile(file, callback){ |
1539 | 1598 | // http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects |
1540 | | -if( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){ |
| 1599 | +if( !file.type && (safari || ((file.size % 4096) === 0 && (file.size <= 102400))) ){ |
1541 | 1600 | if( FileReader ){ |
1542 | 1601 | try { |
1543 | | -var Reader = new FileReader(); |
| 1602 | +var reader = new FileReader(); |
1544 | 1603 |
|
1545 | | -_one(Reader, _readerEvents, function (evt){ |
| 1604 | +_one(reader, _readerEvents, function (evt){ |
1546 | 1605 | var isFile = evt.type != 'error'; |
1547 | | -callback(isFile); |
1548 | 1606 | if( isFile ){ |
1549 | | -Reader.abort(); |
| 1607 | +reader.abort(); |
| 1608 | +callback(isFile); |
| 1609 | +} |
| 1610 | +else { |
| 1611 | +callback(false, reader.error); |
1550 | 1612 | } |
1551 | 1613 | }); |
1552 | 1614 |
|
1553 | | -Reader.readAsDataURL(file); |
| 1615 | +reader.readAsDataURL(file); |
1554 | 1616 | } catch( err ){ |
1555 | | -callback(false); |
| 1617 | +callback(false, err); |
1556 | 1618 | } |
1557 | 1619 | } |
1558 | 1620 | else { |
1559 | | -callback(null); |
| 1621 | +callback(null, new Error('FileReader is not supported')); |
1560 | 1622 | } |
1561 | 1623 | } |
1562 | 1624 | else { |
|
1565 | 1627 | } |
1566 | 1628 |
|
1567 | 1629 |
|
| 1630 | +function _isEntry(item){ |
| 1631 | +return item && (item.isFile || item.isDirectory); |
| 1632 | +} |
| 1633 | + |
| 1634 | + |
1568 | 1635 | function _getAsEntry(item){ |
1569 | 1636 | var entry; |
1570 | 1637 | if( item.getAsEntry ){ entry = item.getAsEntry(); } |
|
1576 | 1643 | function _readEntryAsFiles(entry, callback){ |
1577 | 1644 | if( !entry ){ |
1578 | 1645 | // error |
1579 | | -callback('invalid entry'); |
| 1646 | +var err = new Error('invalid entry'); |
| 1647 | +entry = new Object(entry); |
| 1648 | +entry.error = err; |
| 1649 | +callback(err.message, [], [entry]); |
1580 | 1650 | } |
1581 | 1651 | else if( entry.isFile ){ |
1582 | 1652 | // Read as file |
1583 | | -entry.file(function(file){ |
| 1653 | +entry.file(function (file){ |
1584 | 1654 | // success |
1585 | 1655 | file.fullPath = entry.fullPath; |
1586 | | -callback(false, [file]); |
| 1656 | +callback(false, [file], [file]); |
1587 | 1657 | }, function (err){ |
1588 | 1658 | // error |
1589 | | -callback('FileError.code: '+err.code); |
| 1659 | +entry.error = err; |
| 1660 | +callback('FileError.code: ' + err.code, [], [entry]); |
1590 | 1661 | }); |
1591 | 1662 | } |
1592 | 1663 | else if( entry.isDirectory ){ |
1593 | | -var reader = entry.createReader(), result = []; |
| 1664 | +var |
| 1665 | +reader = entry.createReader() |
| 1666 | +, firstAttempt = true |
| 1667 | +, files = [] |
| 1668 | +, all = [entry] |
| 1669 | +; |
1594 | 1670 |
|
1595 | | -var onerror = function() { |
| 1671 | +var onerror = function (err){ |
1596 | 1672 | // error |
1597 | | -callback('directory_reader'); |
| 1673 | +entry.error = err; |
| 1674 | +callback('DirectoryError.code: ' + err.code, files, all); |
1598 | 1675 | }; |
1599 | | -var ondone = function ondone(entries) { |
| 1676 | +var ondone = function ondone(entries){ |
| 1677 | +if( firstAttempt ){ |
| 1678 | +firstAttempt = false; |
| 1679 | +if( !entries.length ){ |
| 1680 | +entry.error = new Error('directory is empty'); |
| 1681 | +} |
| 1682 | +} |
| 1683 | + |
1600 | 1684 | // success |
1601 | | -if ( entries.length ) { |
| 1685 | +if( entries.length ){ |
1602 | 1686 | api.afor(entries, function (next, entry){ |
1603 | | -_readEntryAsFiles(entry, function (err, files){ |
| 1687 | +_readEntryAsFiles(entry, function (err, entryFiles, allEntries){ |
1604 | 1688 | if( !err ){ |
1605 | | -result = result.concat(files); |
| 1689 | +files = files.concat(entryFiles); |
1606 | 1690 | } |
| 1691 | +all = all.concat(allEntries); |
1607 | 1692 |
|
1608 | 1693 | if( next ){ |
1609 | 1694 | next(); |
|
1615 | 1700 | }); |
1616 | 1701 | } |
1617 | 1702 | else { |
1618 | | -callback(false, result); |
| 1703 | +callback(false, files, all); |
1619 | 1704 | } |
1620 | 1705 | }; |
1621 | 1706 |
|
|
1740 | 1825 | _type = 0; |
1741 | 1826 | onHover.call(evt[currentTarget], false, evt); |
1742 | 1827 |
|
1743 | | -api.getDropFiles(evt, function (files){ |
1744 | | -onDrop.call(evt[currentTarget], files, evt); |
| 1828 | +api.getDropFiles(evt, function (files, all){ |
| 1829 | +onDrop.call(evt[currentTarget], files, all, evt); |
1745 | 1830 | }); |
1746 | 1831 | }); |
1747 | 1832 | } |
|
2533 | 2618 | }); |
2534 | 2619 |
|
2535 | 2620 | this.each(function (file){ |
2536 | | -next(file, data, queue, arg); |
| 2621 | +try{ |
| 2622 | +next(file, data, queue, arg); |
| 2623 | +} |
| 2624 | +catch( err ){ |
| 2625 | +api.log('FileAPI.Form._to: ' + err.message); |
| 2626 | +complete(err); |
| 2627 | +} |
2537 | 2628 | }); |
2538 | 2629 |
|
2539 | 2630 | queue.check(); |
|
2761 | 2852 | var _this = this, options = this.options; |
2762 | 2853 |
|
2763 | 2854 | FormData.toData(function (data){ |
2764 | | -// Start uploading |
2765 | | -options.upload(options, _this); |
2766 | | -_this._send.call(_this, options, data); |
| 2855 | +if( data instanceof Error ){ |
| 2856 | +_this.end(0, data.message); |
| 2857 | +} |
| 2858 | +else{ |
| 2859 | +// Start uploading |
| 2860 | +options.upload(options, _this); |
| 2861 | +_this._send.call(_this, options, data); |
| 2862 | +} |
2767 | 2863 | }, options); |
2768 | 2864 | }, |
2769 | 2865 |
|
|
0 commit comments