Excel文件上传

1,导入市场活动:

1)把用户计算机上的excel文件上传到服务器(文件上传)
2)使用java解析excel文件,获取excel文件中的数据
3)把解析出来的数据添加数据库中
4)返回响应信息

技术准备:
1)文件上传:
fileuploadtest.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
%>
<html>
<head>
    <base href="<%=basePath%>">
    <title>演示文件上传</title>
</head>
<body>
<!--
    文件上传的表单三个条件:
    1.表单组件标签必须用:<input type="file">
      <input type="text|password|radio|checkbox|hidden|button|submit|reset|file">
                      <select>,<textarea>等
    2.请求方式只能用:post
      get:参数通过请求头提交到后台,参数放在URL后边;只能向后台提交文本数据;对参数长度有限制;数据不安全;效率高,有缓存
      post:参数通过请求体提交到后台;既能能提交文件数据,又能够提交二进制数据;理论上对参数长度没有限制;相对安全;效率相对较低
    3.表单的编码格式只能用:multipart/form-data
      根据HTTP协议的规定,浏览器每次向后台提交参数,都会对参数进行统一编码;默认采用的编码格式是urlencoded,这种编码格式只能对文本数据进行编码;
      浏览器每次向后台提交参数,都会首先把所有的参数转换成字符串,然后对这些数据统一进行urlencoded编码;
      文件上传的表单编码格式只能用multipart/form-data:
	  格式是:enctype="multipart/form-data"
-->
<form action="workbench/activity/fileUpload.do" method="post" enctype="multipart/form-data">
    <input type="file" name="myFile"><br>
    <input type="text" name="userName"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

​ ActivityController
​ |->fileUpload()

配置springmvc的文件上传解析器


<!-- 配置文件上传解析器 id:必须是multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="#{1024*1024*80}"/>
        <property name="defaultEncoding" value="utf-8"/>
    </bean>

配置所必须的文件上传解析器之后才能够继续写代码.

 /**MultipartFile 这个是springmvc 专门用来封装文件的类.
	
     * 配置springmvc的文件上传解析器
     *
     */
    @RequestMapping("/workbench/activity/fileUpload.do")
    public @ResponseBody Object fileUpload(String userName, MultipartFile myFile) throws Exception{
        //把文本数据打印到控制台
        System.out.println("userName="+userName);
        //把文件在服务指定的目录中生成一个同样的文件
        String originalFilename=myFile.getOriginalFilename();
		//Original 中文翻译为原始的,起初的,原先的.
		//File file=new File("D:\\course\\18-CRM\\阶段资料\\serverDir\\"+originalFilename); 这个File有两个构造方法可以用
        File file=new File("D:\\course\\18-CRM\\阶段资料\\serverDir\\",originalFilename);//路径必须手动创建好,文件如果不存在,会自动创建
        myFile.transferTo(file);

        //返回响应信息
        ReturnObject returnObject=new ReturnObject();
        returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
        returnObject.setMessage("上传成功");
        return returnObject;
    }

​ 2)使用java解析excel文件:iText,apache-poi
​ 关于办公文档插件使用的基本思想:把办公文档的所有元素封装成普通的Java类,程序员通过操作这些类达到操作办公文档目的。
文件---------HSSFWorkbook
页-----------HSSFSheet
行-----------HSSFRow
列-----------HSSFCell


/**
 * 使用apache-poi解析excel文件
 */
public class ParseExcelTest {
    public static void main(String[] args) throws Exception{
        //根据excel文件生成HSSFWorkbook对象,封装了excel文件的所有信息
        InputStream is=new FileInputStream("D:\\course\\18-CRM\\阶段资料\\serverDir\\aaa.xls");
        HSSFWorkbook wb=new HSSFWorkbook(is);
        //根据wb获取HSSFSheet对象,封装了一页的所有信息
        HSSFSheet sheet=wb.getSheetAt(0);//页的下标,下标从0开始,依次增加
        //根据sheet获取HSSFRow对象,封装了一行的所有信息
        HSSFRow row=null;
        HSSFCell cell=null;
        for(int i=0;i<=sheet.getLastRowNum();i++) {//sheet.getLastRowNum():最后一行的下标
            row=sheet.getRow(i);//行的下标,下标从0开始,依次增加

            for(int j=0;j<row.getLastCellNum();j++) {//row.getLastCellNum():最后一列的下标+1
                //根据row获取HSSFCell对象,封装了一列的所有信息
                cell=row.getCell(j);//列的下标,下标从0开始,依次增加

                //获取列中的数据
                System.out.print(HSSFUtils.getCellValueForStr(cell)+" ");
            }

            //每一行中所有列都打完,打印一个换行
            System.out.println();
        }
    }
}

image-20221112211047256

把上面图片中的代码封装成工具类中的方法,因为是重复的代码

/**
 * 关于excel文件操作的工具类
 */
public class HSSFUtils {
    /**
     * 从指定的HSSFCell对象中获取列的值
     * @return
     */
    public static String getCellValueForStr(HSSFCell cell){
        String ret="";
        if(cell.getCellType()==HSSFCell.CELL_TYPE_STRING){
            ret=cell.getStringCellValue();
        }else if(cell.getCellType()==HSSFCell.CELL_TYPE_NUMERIC){
            ret=cell.getNumericCellValue()+"";
        }else if(cell.getCellType()==HSSFCell.CELL_TYPE_BOOLEAN){
            ret=cell.getBooleanCellValue()+"";
        }else if(cell.getCellType()==HSSFCell.CELL_TYPE_FORMULA){
            ret=cell.getCellFormula();
        }else{
            ret="";
        }

        return ret;
    }
}

上面写的是不插入到数据库的,下面的代码是仿照实际工作中导入文件肯定是要插入到数据库的.

我只把部分重点的代码写一下

Controller层

@RequestMapping("/workbench/activity/importActivity.do")
    public @ResponseBody Object importActivity(MultipartFile activityFile,String userName,HttpSession session){
        System.out.println("userName="+userName);
        User user=(User) session.getAttribute(Contants.SESSION_USER);
        ReturnObject returnObject=new ReturnObject();
        try {
            //把excel文件写到磁盘目录中
            /*String originalFilename = activityFile.getOriginalFilename();
            File file = new File("D:\\course\\18-CRM\\阶段资料\\serverDir\\", originalFilename);//路径必须手动创建好,文件如果不存在,会自动创建
            activityFile.transferTo(file);*/

            //解析excel文件,获取文件中的数据,并且封装成activityList
            //根据excel文件生成HSSFWorkbook对象,封装了excel文件的所有信息
            //InputStream is=new FileInputStream("D:\\course\\18-CRM\\阶段资料\\serverDir\\"+originalFilename);

            InputStream is=activityFile.getInputStream();
            HSSFWorkbook wb=new HSSFWorkbook(is);
            //根据wb获取HSSFSheet对象,封装了一页的所有信息
            HSSFSheet sheet=wb.getSheetAt(0);//页的下标,下标从0开始,依次增加
            //根据sheet获取HSSFRow对象,封装了一行的所有信息
            HSSFRow row=null;
            HSSFCell cell=null;
            Activity activity=null;
            List<Activity> activityList=new ArrayList<>();
            for(int i=1;i<=sheet.getLastRowNum();i++) {//sheet.getLastRowNum():最后一行的下标
                row=sheet.getRow(i);//行的下标,下标从0开始,依次增加
                activity=new Activity();
                activity.setId(UUIDUtils.getUUID());
                activity.setOwner(user.getId());
                activity.setCreateTime(DateUtils.formateDateTime(new Date()));
                activity.setCreateBy(user.getId());

                for(int j=0;j<row.getLastCellNum();j++) {//row.getLastCellNum():最后一列的下标+1
                    //根据row获取HSSFCell对象,封装了一列的所有信息
                    cell=row.getCell(j);//列的下标,下标从0开始,依次增加

                    //获取列中的数据
                    String cellValue=HSSFUtils.getCellValueForStr(cell);
                    if(j==0){
                        activity.setName(cellValue);
                    }else if(j==1){
                        activity.setStartDate(cellValue);
                    }else if(j==2){
                        activity.setEndDate(cellValue);
                    }else if(j==3){
                        activity.setCost(cellValue);
                    }else if(j==4){
                        activity.setDescription(cellValue);
                    }
                }

                //每一行中所有列都封装完成之后,把activity保存到list中
                activityList.add(activity);
            }

            //调用service层方法,保存市场活动
            int ret=activityService.saveCreateActivityByList(activityList);

            returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
            returnObject.setRetData(ret);
        }catch (Exception e){
            e.printStackTrace();
            returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
            returnObject.setMessage("系统忙,请稍后重试....");
        }

        return returnObject;
    }

还有前端页面,因为上传文件,所以跟普通参数不一样

//导入按钮点击后页面会弹出一个窗口

<!-- 导入市场活动的模态窗口 -->
    <div class="modal fade" id="importActivityModal" role="dialog">
        <div class="modal-dialog" role="document" style="width: 85%;">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal">
                        <span aria-hidden="true">×</span>
                    </button>
                    <h4 class="modal-title" id="myModalLabel">导入市场活动</h4>
                </div>
                <div class="modal-body" style="height: 350px;">
                    <div style="position: relative;top: 20px; left: 50px;">
                        请选择要上传的文件:<small style="color: gray;">[仅支持.xls]</small>
                    </div>
                    <div style="position: relative;top: 40px; left: 50px;">
                        <input type="file" id="activityFile">
                    </div>
                    <div style="position: relative; width: 400px; height: 320px; left: 45% ; top: -40px;" >
                        <h3>重要提示</h3>
                        <ul>
                            <li>操作仅针对Excel,仅支持后缀名为XLS的文件。</li>
                            <li>给定文件的第一行将视为字段名。</li>
                            <li>请确认您的文件大小不超过5MB。</li>
                            <li>日期值以文本形式保存,必须符合yyyy-MM-dd格式。</li>
                            <li>日期时间以文本形式保存,必须符合yyyy-MM-dd HH:mm:ss的格式。</li>
                            <li>默认情况下,字符编码是UTF-8 (统一码),请确保您导入的文件使用的是正确的字符编码方式。</li>
                            <li>建议您在导入真实数据之前用测试文件测试文件导入功能。</li>
                        </ul>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                    <button id="importActivityBtn" type="button" class="btn btn-primary">导入</button>
                </div>
            </div>
        </div>
    </div>
//给"导入"按钮添加单击事件
		$("#importActivityBtn").click(function () {
			//收集参数
			var activityFileName=$("#activityFile").val();
			//截取后缀文件类型是不是xls,需要进行校验
			var suffix=activityFileName.substr(activityFileName.lastIndexOf(".")+1).toLocaleLowerCase();//xls,XLS,Xls,xLs,....
			if(suffix!="xls"){
				alert("只支持xls文件");
				return;
			}
            //获取文件,这个方法获取的就是整个文件,
			var activityFile=$("#activityFile")[0].files[0];
            //判断一下文件的大小是不是符合需求标准5M
			if(activityFile.size>5*1024*1024){
				alert("文件大小不超过5MB");
				return;
			}

			//FormData是ajax提供的接口,可以模拟键值对向后台提交参数;
			//FormData最大的优势是不但能提交文本数据,还能提交二进制数据
			var formData=new FormData();
			formData.append("activityFile",activityFile);
			formData.append("userName","张三");

			//发送请求
			$.ajax({
				url:'workbench/activity/importActivity.do',
				data:formData,
				processData:false,//设置ajax向后台提交参数之前,是否把参数统一转换成字符串:true--是,false--不是,默认是true
				contentType:false,//设置ajax向后台提交参数之前,是否把所有的参数统一按urlencoded编码:true--是,false--不是,默认是true
				type:'post',
				dataType:'json',
				success:function (data) {
					if(data.code=="1"){
						//提示成功导入记录条数
						alert("成功导入"+data.retData+"条记录");
						//关闭模态窗口
						$("#importActivityModal").modal("hide");
						//刷新市场活动列表,显示第一页数据,保持每页显示条数不变
						queryActivityByConditionForPage(1,$("#demo_pag1").bs_pagination('getOption', 'rowsPerPage'));
					}else{
						//提示信息
						alert(data.message);
						//模态窗口不关闭
						$("#importActivityModal").modal("show");
					}
				}
			});
		});
posted @ 2022-11-13 18:11  哩个啷个波  阅读(420)  评论(0)    收藏  举报