安卓手机中使用html的input file 获取不到文件类型和文件名

2017-04-27 07:30:00input标签,file,javascript问题

在部分安卓手机上,input file拿不到文件信息,怎么回事?
image.png

对name解码如下:
image.png

国外有大神读取文件流获取,难道只有这一种方法了吗?
http://stackoverflow.com/questions/30689030/html-file-input-on-chrome-for-android-missing-extension-and-mime-type

网友回答:

  • jsoncode jsoncode 2017-4-28 2:58 回复:
    已被采纳

看来这个问题还是比较难解决的,那我就自己来解决一下吧

既然直接读取file.type是空字符串,那就只能从文件流里面读取文件头信息了。

参考题中的链接方案,这里优化了一下

function checkFileType(type, file, back) {
    /**
     * type png jpg mp4 ...
     * file input.change=> this.files[0]
     * back callback(boolean)
     */
    // http://www.garykessler.net/library/file_sigs.html
    var args = arguments;
    if (args.length != 3) {
        back(0);
    }
    var type = args[0]; // type = '(png|jpg)' , 'png'
    var file = args[1];
    var back = typeof args[2] == 'function' ? args[2] : function() {};
    if (file.type == '') {
        // 如果系统无法获取文件类型,则读取二进制流,对二进制进行解析文件类型
        var imgType = [
            'ff d8 ff', //jpg
            '89 50 4e', //png
        '0 0 0 14 66 74 79 70 69 73 6F 6D', //mp4
        '0 0 0 18 66 74 79 70 33 67 70 35', //mp4
        '0 0 0 0 66 74 79 70 33 67 70 35', //mp4
        '0 0 0 0 66 74 79 70 4D 53 4E 56', //mp4
        '0 0 0 0 66 74 79 70 69 73 6F 6D', //mp4

        '0 0 0 18 66 74 79 70 6D 70 34 32', //m4v
        '0 0 0 0 66 74 79 70 6D 70 34 32', //m4v

        '0 0 0 14 66 74 79 70 71 74 20 20', //mov
        '0 0 0 0 66 74 79 70 71 74 20 20', //mov
        '0 0 0 0 6D 6F 6F 76', //mov

        '4F 67 67 53 0 02', //ogg
        '1A 45 DF A3', //ogg
    ];
    var typeName = [
        'jpg',
        'png',
        'mp4',
        'mp4',
        'mp4',
        'mp4',
        'mp4',
        'm4v',
        'm4v',
        'mov',
        'mov',
        'mov',
        'ogg',
        'ogg',
    ];
    var sliceSize = /png|jpg|jpeg/.test(type) ? 3 : 12;
    var reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.addEventListener("load", function(e) {
        var slice = e.target.result.slice(0, sliceSize);
        reader = null;
        if (slice && slice.byteLength == sliceSize) {
            var view = new Uint8Array(slice);
            var arr = [];
            view.forEach(function(v) {
                arr.push(v.toString(16));
            });
            view = null;
            console.log(arr.join(' '));
            var idx = arr.join(' ').indexOf(imgType);
            if (idx > -1) {
                back(typeName[idx]);
                console.log(typeName[idx]);
            } else {
                back(false);
            }
        } else {
            back(false);
        }

    });
} else {
    var type = file.name.match(/\.(\w+)$/)[1];
    back(type);
}

}

使用方法:

input.addEventListener(function(){
    var file = this.files[0];
    if(file.type==''){
        // 第一个参数支持单类型,或多类型,多类型时用竖线分隔,用于生成正则式
        checkFileType('(png|jpg|jpeg|mp4|mov|m4v|ogg)',file,function(fileType){
            console.log(fileType);
            //'png'
        });
        checkFileType('jpg',file,function(fileType){
            console.log(fileType);
            //false
        });
    }
});

只做了对png,jpg,jpeg,mp4,mov,m4v,ogg几个常用格式判断,其他文件类型的文件头信息,可以查看这里:
http://www.garykessler.net/li...

  • js5323 js5323 2018-4-23 6:28 回复:jsoncode

    HONORBND-AL10 遇到这种问题。。。

  • chack chack 2019-3-1 10:54 回复:jsoncode

    这样即使获取到文件类型,那传的文件名字怎么获取呢

  • jsoncode jsoncode 2019-3-4 5:25 回复:jsoncode
    文件名并不是重要信息,我也没有遇到过这个需求,所以,我用文件md5做的文件名

  • lixg lixg 2019-7-26 5:09 回复:jsoncode

    'D0 CF 11 E0 A1 B1 1A E1': 'DOC, DOT, PPS, PPT, XLA, XLS, WIZ',
    '50 4B 03 04 14 00 06 00': 'DOCX, PPTX, XLSX',
    这种 流对应多个类型的岂不是也没法整了?求大神解惑,或者其他办法指引一二。


  • lixg lixg 2019-7-26 5:08 回复:

    'D0 CF 11 E0 A1 B1 1A E1': 'DOC, DOT, PPS, PPT, XLA, XLS, WIZ',
    '50 4B 03 04 14 00 06 00': 'DOCX, PPTX, XLSX',
    这种 流对应多个类型的岂不是也没法整了?求大神解惑,或者其他办法指引一二。

    • jsoncode jsoncode 2019-7-29 6:21 回复:lixg
      请参考我放的那个链接,自己写匹配逻辑就行了,头信息很多,不只是你放出来的这么短几个字节,可以多匹配几个字节,更加精准 .还有,我这里是一个思路,我也在学习,不知道还有没有其他方法