ajax上传Excel文件,解析为List,获取文件内容

来源:互联网 发布:手游编程用什么软件 编辑:程序博客网 时间:2024/05/22 01:49

需求

需求分析

现有批量上传的需求,通过上传Excel文件,获取用户uidList

流程分析

  • 页面Excel文件输入框
    <tr>            <td>批量文件:</td>            <td><input type="file"  id="idFile" name="idFile" class="  " /></td>    </tr>
  • 输入框事件
       //上传 excel文件    function importExcel(formData) {        $.ajax({            url: "lehai/giveMedalToUserAction!readUserIdList",            type: 'POST',            cache: false,            data: formData,            dataType : "json",            processData: false,            contentType: false        }).done(function(msg) {            if (msg.result == 1) {            }            if (msg.result == 0) {                showMessage(""+msg.resultText );                $("#idFile").val("");            }        }).fail(function(msg) {            showMessage("读取错误!");        });    }    //选择文件事件    $("#idFile").change(function(){        $("#roomid").val("");        $("#showid").val("");        var str=$("#idFile").val();        if (checkFileType(str)){            var formData = new FormData();            formData.append('idFile', $('#idFile')[0].files[0]);            importExcel(formData);        }    });    function checkFileType(str){        var index=str.lastIndexOf('.');        var strtype=str.substr(index,str.length);        strtype=strtype.toLowerCase();        if (strtype == "") {            return false;        }else if (strtype == ".xls"){            return true;        }else{            $("#idFile").val("");            showMessage("文件格式为.xls");            return false;        }        return false;    }    function checkFile(filename)    {        var str = filename.val()        if (str.length == 0) {            showMessage("批量发放文件不能为空!");            return false;        }        return true;    }

说明: 通过jquery的 change()事件,在选择文件后,触发ajax上传方法importExcel().
不同的是,文件的ajax上传略有不同,下面比较一下普通的ajax和文件上传ajax的区别。

1.普通的jax

$.ajax({       url : "http://localhost:8080/STS/rest/user",       type : "POST",       data : $( '#postForm').serialize(),       success : function(data) {            $( '#serverResponse').html(data);       },       error : function(data) {            $( '#serverResponse').html(data.status + " : " + data.statusText + " : " + data.responseText);       }  }); 

通常我们提交(使用submit button)时,会把form中的所有表格元素的name与value组成一个queryString,提交到后台。这用jQuery的方法来说,就是serialize。
通过$(‘#postForm’).serialize()可以对form表单进行序列化,从而将form表单中的所有参数传递到服务端。

但是上述方式,只能传递一般的参数,上传文件的文件流是无法被序列化并传递的。
不过如今主流浏览器都开始支持一个叫做FormData的对象,有了这个FormData,我们就可以轻松地使用Ajax方式进行文件上传了。

2.文件ajax上传

<form id="uploadForm" enctype="multipart/form-data">    <input id="file" type="file" name="file"/>    <button id="upload" type="button">upload</button></form>

javascript代码:

$.ajax({    url: '/upload',    type: 'POST',    cache: false,    data: new FormData($('#uploadForm')[0]),    processData: false,    contentType: false}).done(function(res) {}).fail(function(res) {});

可以看到,主要的区别是文件的ajax上传使用了FormData对象添加字段方式。


3.FormData 对象的简介

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个”表单”.比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件. 参考链接

FormData.append

本方法用于向已存在的键添加新的值,如该键不存在,新建之。

语法

formData.append(name, value);
formData.append(name, value, filename);

注: 通过 FormData.append()方法赋给字段的值若是数字会被自动转换为字符(字段的值可以是一个Blob对象,一个File对象,或者一个字符串,剩下其他类型的值都会被自动转换成字符串).

参数解释

name
键 (key), 对应表单域

value

表单域的值

filename (optional)
The filename reported to the server (a USVString), when a Blob or File is passed as the second parameter. The default filename for Blob objects is “blob”.
FormData.delete

将一对键和值从 FormData 对象中删除。

formData.delete(username);
FormData.get

返回给定键的第一个值

formData.append(‘username’, ‘Justin’);
formData.append(‘username’, ‘Chris’);
formData.get(username); // “Justin”
FormData.getAll

返回给定键的所有值

formData.append(‘username’, ‘Justin’);
formData.append(‘username’, ‘Chris’);
formData.getAll(username); // [“Justin”, “Chris”]
FormData.has

检查是否包含给定键,返回 true 或 false

formData.has(username);
FormData.set

设置给定键的值

formData.set(name, value);
formData.set(name, value, filename);

3.1 Formdata使用

Constructor

FormData()

想得到一个FormData对象:
var formdata = new FormData();
W3c草案提供了三种方案来获取或修改FormData。

方案1:创建一个空的FormData对象,然后再用append方法逐个添加键值对:
var formdata = new FormData();
formdata.append(“name”, “呵呵”);
formdata.append(“url”, “http://www.baidu.com/“);

方案2:取得form元素对象,将它作为参数传入FormData对象中!
var formobj = document.getElementById(“form”);
var formdata = new FormData(formobj);
方案3:利用form元素对象的getFormData方法生成它!
var formobj = document.getElementById(“form”);
var formdata = formobj.getFormData()

值得注意几点:

  1. processData设置为false。因为data值是FormData对象,不需要对数据做处理。
  2. cache设置为false,上传文件不需要缓存。
  3. contentType设置为false,不设置contentType值,因为是由表单构造的FormData对象,且已经声明了属性
  4. enctype=”multipart/form-data”,所以这里设置为false。

  • 后台代码

后台的代码主要是对Excel文件的解析。

1.文件流接收

protected File idFile;

2.Excel 解析

思路是:通过现有的ExcelAPI,jxl或者POI都可以,解析数据并保存到List对象中,List idList =new ArrayList();。因为我们只需要第一列的数据,因而使用单个List即可。如果是多列数据,可以像这样List

   public void readUserIdList() {        logger.info("into importExcel");        List<String> idList =new ArrayList<String>();        if (!idFile.exists()){            printJsonResult(SystemConstants.ERROR_RESULT_TEMPALTE,SystemConstants.OPERATE_ERROR);        }else {            try {                jxl.Workbook book = jxl.Workbook.getWorkbook(idFile);                int uidNo = 0;                int row_start = 0;                jxl.Sheet sheet = book.getSheet(0);                for (int i = row_start; i < sheet.getRows(); i++) {                    String uid = sheet.getCell(uidNo, i).getContents();                    idList.add(uid);                }                if (CollectionUtils.isEmpty(idList)) {                    printJsonResult(SystemConstants.ERROR_RESULT_TEMPALTE,ResourceConstants.EXCEL_DATA_NULL);                }else{                    request.getSession().setAttribute("idList", idList);                    printJsonResult(SystemConstants.SUCCESS_RESULT_TEMPALTE, SystemConstants.OPERATE_SUCCESS);                }            } catch (Exception ex) {                logger.error("importExcel ex={}",ex);            }        }        logger.info("importExcel idStr={}", idList);    }

上述示例使用jxl解析Excel,目的是读取excel文件的第一列数据到一个List中,Excel文件格式要求如下:
Excel文件第一列为传递的数据,如果是多列只需要循环即可:关于Excel的更多操作请参考以下文章,该文章使用POI解析Excel,虽然方法有区别但是原理想通。
参考

| field1    | | field2    | | field3    | | field4    | 
  • 数据处理

数据解析到了List里,这下谁都会用了。自己后台使用,或者放到request、session中返回页面都可以。

问题解决

总结: 没有什么技术难点,重要的是学会使用一些第三方的API,这个对快速简洁开发很重要。

个人博客
感兴趣的可以关注我的个人博客:九点钟的太阳