js利用input上传文件的正确方式

正文开始

首先是建个input

注意项: accept里禁止写* 通配符 多选的配置:multiple

方法1 小文件上传

利用FileReader获取文件 体验即时显示文件信息

infoTable.find('.uploadInput').change(function () {
    var fileObj = $(this);
    var inputName = $(this).attr('name');
    var fileNode = fileObj[0].files[0];
    var reader = new FileReader();
    reader.onload = function (e) {
    var base64Data = e.target.result;
    fileData[inputName] = dataURLtoBlob(base64Data);
    };
    if(fileNode) reader.readAsDataURL(fileNode);
    });

base64的字符串可以转为blob文件

function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(',');
    var mimeArray = arr[0].match(/:(.*?);/);
    if(!mimeArray || !mimeArray[1]) {
        console.log(mimeArray);
        console.log('no find 1');
        return;
    }
    var mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {type: mime});
}

缺点:

FileReader不支持大文件,大概加载不了500M左右以上的超大文件; 文件提交的内容不是原生的文件流对象,而是base64的字符串或是转换成blob二进制文件,所以从它们俩个内容都是获取不到文件名的,需要在获取文件信息时捕获文件名,跟blob对象一起打包提交给后台。

优点:

可以在选择文件时 实时预览文件的信息(缩略图、文件名、文件大小,图片宽高)。 利用这个方法,做一个批量上传的插件。只要将每次批量选择的结果:$(this)[0].files 解析成base64的字符串,显示在列表中,缓存为临时对象,即可控制上传。

方法2 大文件上传

利用原生js方法 new FormData(form.node); 打包生成原生的文件流对象 举例:

$('#demoForm').on('submit', function(e) {
   e.preventDefault();
   var form_ = $(this);
   var formData = new FormData(form[0]);
   $.post({
     url: '',
     data: formData,
   })
})

优点: 原生方法,后台可以用files对象获取文件的所有信息 缺点: 前端不能实现:预览文件效果,提前获取文件信息。 多个文件是一次上传,不能改为单个文件上传。 不能用同一个文件input动态创建多个文件,只能在页面上提前生成多个file.input再选择上传。 因为文件流内容无法存入页面dom。

方法1 选择本地文件,获取base64内容显示在本地,即将上传的demo

 var fileData = [];
        var bindFIleInputEven = function (jqInput) {
            var addFileList = function(fileNode) {
                var reader = new FileReader();
                var fileName = fileNode.name;
                var isImg =  /(jpg|jpeg|gif|png|bmp|webp)$/i.test(fileName);
                var bs = reader.readAsBinaryString, spark = bs ? new SparkMD5() : new SparkMD5.ArrayBuffer();
                reader.onload = function (e) {
                    var fileBase64 = this.result;
                    spark.append(fileBase64);
                    //创建文件成功后 删除input防止同一个文件不支持二次选择
                    var newInput = $(jqInput.prop('outerHTML'));
                    jqInput.after(newInput);
                    bindFIleInputEven(newInput);
                    let imgHash = spark.end();
                    if(fileData[imgHash]) {
                        alert('file exist');
                        return;
                    }
                    fileData[imgHash] = fileBase64;
                    var newFileDom = $('');
                    infoTable.find('.appendFileBox').append(newFileDom);
                    newFileDom.find('.removeFileBtn').click(function () {
                        newFileDom.remove();
                        delete fileData[imgHash];
                    })
                };
                reader.readAsDataURL(fileNode);
            };
            jqInput.change(function () {
                var fileObj = $(this);
                var fileNodesList = fileObj[0].files;
                $.each(fileNodesList, function (n, fileNode) {
                    addFileList(fileNode);
                });
            });
        };
        var fileUrls = [];
        bindFIleInputEven(infoTable.find('.addFileBtn input')); 
        var uploadFiles = function(base64List, index) {
            var firstKey = Object.keys(fileData)[0];
            var firstStr = base64List[firstKey];
            var album = $(infoTable.find('.appendFileBox').find('.thumbnail').eq(index));
            album.addClass('showLoading');
            var fileName = album.attr('data-name');
            front.postAndDone({
                url: '/index/support/upload_warranty_file',
                postData: {
                    fileName: fileName,
                    base64: firstStr,
                },
                successKey: 'code',
                successVal: 1,
                successFunc: function (res) {
                    lrBox.msgTisf(res.msg);
                    delete base64List[firstKey];
                    $(infoTable.find('.appendFileBox').find('.thumbnail').eq(index)).removeClass('showLoading').addClass('showSuccess');
                    if(Object.keys(fileData).length) {
                        index++;
                        uploadFiles(base64List, index);
                    } else {
                        lrBox.noLoading();
                        warrantyBox.trigger('submit');
                    }
                    var newUrl = res.data.url;
                    fileUrls.push({
                        'fileName': fileName,
                        'url': newUrl,
                    })
                },
                errorFunc: function (res) {
                    $(infoTable.find('.appendFileBox').find('.thumbnail').eq(index)).removeClass('loading').addClass('showError');
                    lrBox.noLoading();
                    lrBox.msgTisf(res.msg);
                }
            })
        };

文件MD5算法js: /upload/post_files/484/spark-md5.js

正文结束

input file accept定义图片、视频 全网最齐全的特殊符号,使用unicode编码 从1到10000...