自己还是一个菜鸟的时候,有次项目经理让我用Java做一个多文件上传的功能。那时候技术学得很渣,最多只能够实现单文件上传。做了一个星期都没有做出来,于是项目经理不留半点情面,当着办公室所有人的面痛批我一顿,让我颜面扫地,当时我对了他一句我大不了辞职嘛。那是我的悲伤记忆,最终和上级领导沟通半天后,确定留下来继续干。经历一些事情后,一个人总是要成长的,我也一样。如果那个简单的功能都做不出来,那我还能够干什么呢?除了提升自己我还能干什么呢?

那次的问题最后是使用SWFUpload插件解决多文件上传问题的,多年之后的今天已经对文件上传信手拈来,不管是使用插件还是原生的input标签。现在来分享一下使用原生input标签上传文件的用法。

AJAX实现单文件上传
    <input type="file" name="file" id="uploadFile"  οnchange="uploadExcel()"  accept=".xls,.xlsx">

input标签可以隐藏也可以显示出来,样式怎么好看自己就怎么改,type,name属性不要忘记。主要是触发input标签的单击事件,然后选择文件。accept属性的作用是可以限制文件的选择类型,不在accept里面的类型的文件不会显示出来。对一般人来说还是能起作用。选择好文件后,触发下一个事件onchange,它是在文件选择好以后执行。重点来了,文件选择好以后需要做的事情,上代码:

let fileType = $('#uploadFile').val();
        fileType = fileType.substring(fileType.lastIndexOf('.'));

//文件类型校验
        if(fileType !== '.xls' && fileType !== '.xlsx'){
            return msgError('操作提示:只能上传xls格式或者xlsx格式的文件!');
        }

//获取单个文件
        let file = document.getElementById(`uploadFile`).files[0];

//必须创建一个FormData对象,然后将获取到的文件数据添加到对象中,并且要注意inputFile,解析时需要它。
        let formData = new FormData();
        formData.append('inputFile',file);
        $.ajax({
            url: '{{projcfg.appurl}}/api/cable/cable_manage_route/uploadExcel',
            type: 'post',
            data: formData,
            cache: false,//上传文件无需缓存
            contentType: false,//必须
            processData: false,//用于对data参数进行序列化处理 这里必须false
            success: function (json) {
                if (json.success) {
                    msgSuccess(`消息提示:${json.msg}`);
                    $("#dataTable").datagrid("reload");
                }else {
                    msgError(`错误提示:${json.msg}`);
                }
                $('#importWin').dialog('close');
                $('#uploadFile').parent().html('<input type="file" name="file" id="uploadFile" οnchange="uploadExcel()"  accept=".xls,.xlsx">');
            },
            error: function () {
                msgError(`错误提示:导入Excel文件出现异常,请稍后重试!`);
            },
        });

后端node解析核心代码,使用formidable这个包进行解析,java则可以使用对应的包来进行解析。

var form = new formidable.IncomingForm();   //创建上传表单
            form.encoding = opts.encoding;    //设置字符集
            form.uploadDir = opts.uploadDir;     //设置上传目录
            form.keepExtensions = opts.keepExtensions;     //保留文件后缀名
            form.maxFieldsSize = opts.maxFieldsSize;   //文件大小
            form.parse(req, function (error, fields, files) {
                if (error) {
                    reject(error);
                } else {
                    if(files[opts.file_name]){//有附件上传 和uploadFile的名字一样
                        let filePath = files[opts.file_name].path;
                        let fileType = filePath.substr(filePath.lastIndexOf(".") + 1);
                        if (opts.fileTypes.indexOf(fileType) == -1) {
                            delFile(filePath);
                            reject(`Excel文件格式错误,请上传格式为${opts.fileTypes}类型的文件!`);
                        } else {
                            //处理Excel文件
                            let userId = 8;//req.session.current_user._id;
                            resole(filePath);
                        }
                    }else{//没有附件上传
                        reject('没有附件上传!');
                    }
                }
            });

测试后完全可行,项目已经上线正常运行。

AJAX实现多文件上传

多文件上传和单文件上传类似,只需要做少量的修改即可。

<input type="file" name="upload_file" id="upload_file" οnchange="upload_picture()" accept=".jpg, .png" multiple/>

第一个需要修改的地方是添加一个multiple属性,它的作用是你可以同时选择多个文件。

function upload_picture() {
        //获取文件数据
        let formData = new FormData();
        let files = document.getElementById("upload_file").files;
        formData.enctype = "multipart/form-data";
        let fileArray = [].slice.call(files,0);//类数组转换为数组
        let fileType = '', file = '', fileSize = '';

//第二个需要修改的地方,循环验证选择的文件和添加文件数据到FormData中
        for(let k = 0,klen = fileArray.length; k < klen; k++){
            file = fileArray[k];
            fileType = fileArray[k].name.substring(fileArray[k].name.lastIndexOf('.') + 1);
            if(fileType !== 'jpg' && fileType !== 'png'){
                return layer.msg(`操作提示:只能上传jpg格式或者png格式的图片!`);
            }
            let fileSize = Math.floor(file.size/(1024*1024));
            if(fileSize > 2){
                return layer.msg(`操作提示:只能上传大小不超过2MB的图片!`);
            }
            formData.append(`upload_file${k}`,file);//循环遍历把文件对象插到formData对象上
        }
        if(fileArray.length === 0){
            return layer.msg(`操作提示:请先选择需要上传的图片!`);
        }
        //提交数据
        $.ajax({
            url: '{{projcfg.base}}/api/kfz/model_manage_route/upload_picture.do',
            type: 'post',
            data: formData,
            cache: false,//上传文件无需缓存
            contentType: false,//必须
            processData: false,//用于对data参数进行序列化处理 这里必须false
            success: function (result) {
                if (result.success && result.code === 2000) {
                    layer.msg(`消息提示:${result.msg}`);
                    file_arr = result.data;
                }else {
                    layer.msg(`错误提示:${result.msg}`);
                }
                //重新创建文件上传标签
                $('#upload_file_div').html(`<input type="file" name="upload_file" id="upload_file"  οnchange="upload_picture()" accept=".jpg, .png" multiple/>`);
            },
            error: function () {
                layer.msg(`错误提示:上传图片出现异常,请稍后重试!`);
            },
            timeout: 180000,
            complete: function () {
                //$.messager.progress('close');
            }
        });
    }

后端node解析核心代码:

var form = new formidable.IncomingForm();   //创建上传表单
            form.encoding = opts.encoding;    //设置字符集
            form.uploadDir = opts.uploadDir;     //设置上传目录
            form.keepExtensions = opts.keepExtensions;     //保留文件后缀名
            form.maxFieldsSize = opts.maxFieldsSize;   //文件大小
            form.parse(req, function (error, fields, files) {
                if (error) {
                    reject(error);
                }else {
                    //文件处理
                    let temp_file,file_path,file_type,flag,path_arr = [],obj = {};
                    let type_arr = opts.fileTypes.split('|');
                    Object.keys(files).forEach(function (file_key) {//第三个需要修改的地方,file_key即为上传时添加的不同的名称
                        temp_file = files[file_key];
                        obj = {};
                        if(temp_file){//有附件上传
                            let file_path = temp_file.path;
                            let file_type = file_path.substr(file_path.lastIndexOf("."));
                            flag = flag;
                            type_arr.forEach(function (item) {
                                if(item === file_type){
                                    flag = true;
                                }
                            });
                            if(!flag){
                                delFile(file_path);//文件类型不匹配
                                reject(`图片格式错误,请上传格式为${opts.fileTypes}类型的图片!`);
                            }else {
                                //将图片移动到指定的文件夹
                                let temp_path = path.join(opts.uploadDir, opts.nowDate, 'verification');
                                let desc_path = path.join(temp_path, Math.random().toString().substring(2,12) + file_type);
                                //处理路径
                                obj.file_path = desc_path.replace(/\\/g,'/');
                                obj.file_name = temp_file.name;
                                path_arr.push(obj);
                                mkdirsSync(temp_path,'0779');//创建文件夹
                                fs.renameSync(file_path,desc_path);
                            }
                        }
                    });

if(path_arr.length === Object.keys(files).length){
                        //返回文件路径
                        resole(path_arr);
                    }else{
                        reject('文件上传出现错误,请稍后重试!');
                    }
                }
            });

项目中已经正式采用这种方法,完全可行,目前还没有发现其他问题。

注意事项

如果有文件选择错误的话或者是想重新选择,在不刷新页面的情况下,则需要替换掉原来的input标签。这个好比一次性注射器用一次就扔掉,当然吸毒的除外,每一个用于文件上传的input标签只能使用一次。采用这种处理方式可以将文件上传和数据提交完全分离开来,处理起来非常方便。如果使用form表单提交的方式,则文件上传和其他表单数据一起提交,不排除会容易出现一些未知错误。

原生input标签实现ajax单文件上传和多文件上传相关推荐

  1. Vue中使用file类型input标签,无法使用reset方法清空已经选择的文件【简单粗暴的解决方案】

    这是在一个vue+springboot的小项目中遇到的问题,如图: 看了其他大佬的文章,看到了不少解决方案,但是无济于事,我这里依然报错,我一不做 二不休直接提供一个是十分暴力的解决方案 下面这个是两 ...

  2. SpringMVC 单文件上传与多文件上传

    一.简述 一个javaWeb项目中,文件上传功能几乎是必不可少的,本人在项目开发中也时常会遇到,以前也没怎么去理它,今天有空学习了一下这方面的知识,于是便将本人学到的SpringMVC中单文件与多文件 ...

  3. ajax 怎么input赋值,jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签...

    jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签 发布于 2016-11-25 16:26:40 | 111 次阅读 | 评论: 0 | 来源: ...

  4. html5之input标签学习

    input标签 本文介绍单标签input 基本形式: <input type="" name=""> input标签的属性有以下几种: autofo ...

  5. ajax 解决csrf的3种方法,input标签的文件上传

    ajax 解决csrf的3种方法,input标签的文件上传 参考文章: (1)ajax 解决csrf的3种方法,input标签的文件上传 (2)https://www.cnblogs.com/gyh0 ...

  6. html 文件上传框 input标签

    文件上传框  有时候,需要用户上传自己的文件,文件上传框看上去和其它 文本域差不多,只是它还包含了一个浏览按钮.访问者可以通 过输入需要上传的文件的路径或者点击浏览按钮选择需要上传 的文件. 代码格式 ...

  7. 用input标签 文件,多文件上传

    单个文件,多个文件区别不大,只是需要把多个文件装在一个容器里面,循环遍历即可: 需要注意的 input 标签中name属性,一定要指定: 在这是  fileBase  需要确定method必须是pos ...

  8. ajax上传和下载文件

    ajax上传和下载文件 jQuery本身支持上传文件,但是不支持下载文件,这里要用到的组件是axios. <form class="form-horizontal" meth ...

  9. 使用Ajax以一种形式上传数据和文件吗?

    本文翻译自:Uploading both data and files in one form using Ajax? I'm using jQuery and Ajax for my forms t ...

最新文章

  1. Amazon AWS云计算服务简介
  2. Dubbo源码分析(三)Dubbo中的SPI和自适应扩展机制
  3. C#关闭一个窗口的同时打开另一个窗口
  4. Maven---学习心得---maven的Dependency Mechanism(依赖关系机制)
  5. 编写Play 2的模块,第1部分:使工作正常
  6. 专门讲讲这个MYSQL授权当中的with grant option的作用
  7. oracle 循环select查询的结构集,执行insert到指定表保存
  8. python如何把二进制转文本_在python3中如何把文本转换为二进制
  9. matlab2c使用c++实现matlab函数开发配置全解
  10. 【转】详解GAN代码之逐行解析GAN代码
  11. MyBatis之ResultMap简介,关联对象…
  12. 新版《中国药典》提升中药标准
  13. 视频转文字怎么操作?快把这些方法收好
  14. 【MySQL笔记】视图的创建与使用(VIEW)
  15. 重生之我是赏金猎人-漏洞挖掘(十一)-某SRC储存XSS多次BypassWAF挖掘
  16. webjar的详细使用方式
  17. php riak,PHP操作Riak
  18. 咫尺天涯   三世桃花
  19. HDU 4262 Juggler 树状数组
  20. matlab矩阵行位列维,Matlab—基本操作与矩阵输入

热门文章

  1. 2019-8-23 [Linux] 12.硬盘管理 文件系统 硬盘df展示数据 du统计目录和文件大小 mount使用挂载光驱、硬盘、U盘
  2. python爬虫(个人学习笔记)
  3. 什么是Webpack?如何使用?
  4. 史上最简单的 Spring MVC 教程(九)
  5. 德国首家小米体验店杜塞开业
  6. uniapp全局弹窗(APP端)
  7. 如何做B端,才能让用户爱不释手?
  8. “白骨精”学习法一书中的经典句子 (自用摘抄)
  9. 曾经很要好的同事,离职后就没有联系了,好失落!
  10. markdown的数学公式(详解)