zoukankan      html  css  js  c++  java
  • 使用OCUpload和POI一键上传Excel并解析导入数据库

    一、OCUpload插件的使用

    1.1 OCUpload介绍

      OCUpload (One Click Upload)译成中文就是一键上传的意思。它是JQuery的一个插件。 
      对于传统的文件上传,只能通过form表单,将enctype设置为multipart/form-data,选中文件后还需在页面点击submit提交按钮,提交表单,才能在后台接收上传的文件并进行相关字段解析,上传成功后,页面还要刷新,这样并不符合我们的某些实际需求。如果要用ajax进行文件上传达到不刷新页面的效果,这样也是不对的,因为ajax不支持文件上传,这是因为response原因,一般请求浏览器是会处理服务器输出的response,例如生成png、文件下载等,然而ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。文件的下载是以二进制形式进行的,虽然可以读取到返回的response,但只是读取而已,是无法执行的,说白点就是js无法调用到浏览器的下载处理机制和程序。那这时想要达到上传页面并不刷新的效果怎么把呢???我们可以这么做。

    <iframe name="text" style="display:none"></iframe>
    <form target="text" action="xxx" method="post" enctype="multipart/form-data">
      <input type="file" name="myFile"/>
      <input type="submit" value="upload"/>         
    </form>

      通过这种方式上传文件,刷新的页面就变成了这个iframe,而且设置的隐藏我们看不到,而我们自己所用的页面就不会刷新,通过这种方式达到了一个不刷新页面上传文件的效果。

      而OCUpload就是采用了这种方式,只是进行了封装我们看不到。接下来就讲一讲怎么使用UCOpload。

    1.2 OCUpload的使用步骤

      第一步:将js文件引入页面

    <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.8.3.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery.ocupload-1.1.2.js"></script>

      第二步:在页面中提供任意一个元素

    <input id="myButton" type="button" value="上传"/>

      第三步:调用插件提供的upload方法,动态修改HTML页面元素

    <script type="text/javascript">
        $(function () {
            $("#myButton").upload({
                action: 'regionAction_importXls.action',             //你所要向服务器请求的的路径,必填
                name: 'regionFile',                                 //上传组件的name的值,不写默认是file
                enctype: 'multipart/form-data',                   //mime类型,使用默认就好
                params: {},                             //请求时额外传递的参数,默认是为空的
                onSelect: function (self, element) {            //当用户选择了一个文件后触发事件
                    this.autoSubmit = false;                    //当选择了文件后,关闭自动提交
                },
                onSubmit: function (self, element) {
                },          //提交表单之前触发事件
                autoSubmit: true,                              //是否自动提交,即当选择了文件,自动关闭了选择窗口后,是否自动提交请求。
                onComplete: function (data, self, element) {
                }   //提交表单完成后触发的事件
            });
        });
    </script>

      我们打开页面并上传文件后,发现html页面变成了这样:

     

    二、Apache POI技术

    2.1 POI简介

      Apache POI是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。

      要使用POI,我们需要下载它的开发包,解压如下:

      

      或者在项目中引入POI的依赖:

            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.11</version>
            </dependency>

    2.2 接收上传的文件,并用POI解析

      在客户端上传测试文件:

      

      在Action中提供一个File类型的属性,名称和上传的文件输入框名称一致regionFile

    @Controller
    @Scope("prototype")
    public class RegionAction extends ActionSupport implements ModelDriven<Region> {
        private Region region;
    
        @Autowired
        private IRegionService regionService;
    
        // 属性驱动,接收上传的文件
        private File regionFile;
    
        public void setRegionFile(File regionFile) {
            this.regionFile = regionFile;
        }
    
        /**
         * 区域导入
         *
         * @return
         */
        public String importXls() throws IOException {
            List<Region> regionList = new ArrayList<>();
            //使用POI解析Excel文件
            HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(regionFile));
            //根据名称获得指定Sheet对象
            HSSFSheet hssfSheet = workbook.getSheet("Sheet1");
            //遍历标签页中所有的行
            for (Row row : hssfSheet) {
                int rowNum = row.getRowNum(); // 行号
                // 如果是标题行,结束本次循环,直接进入下一次循环
                if (rowNum == 0) {
                    continue;
                }
                String id = row.getCell(0).getStringCellValue();
                String province = row.getCell(1).getStringCellValue();
                String city = row.getCell(2).getStringCellValue();
                String district = row.getCell(3).getStringCellValue();
                String postcode = row.getCell(4).getStringCellValue();
                // 包装一个区域对象
                Region region = new Region(id, province, city, district, postcode, null, null);
    
                regionList.add(region);
            }
            // 批量保存
            regionService.saveBatch(regionList);
            return NONE;
        }
    
        @Override
        public Region getModel() {
            return region;
        }
    }

       至此,Excel文件的数据就能成功传入到数据库中了

      

    三、pinyin4J

    3.1 简单介绍

      上面导入的数据中,我们发现shortcode和citycode字段都为null,而原excel文件中并没有这两个字段,说明这两个字段需要我们手动生成。shortcode是省市区首字母的简写,比如河北省石家庄市桥西区的shortcode就是HBSJZQX;citycode是城市拼音的简写,比如石家庄市的citycode为shijiazhuang。这时候我们就需要使用pinyin4J来帮我们完成这个工作。

      pinyin4J是一个支持将中文转换到拼音的Java开源类库,它能够根据中文字符获取其对应的拼音,并且拼音的格式可以控制。pinyin4J的基本功能有:

    • 支持同一汉字有多个发音
    • 支持拼音的格式化输出,比如第几声之类的
    • 支持简体中文、繁体中文转换为拼音

      这里是它的官方下载地址:http://pinyin4j.sourceforge.net/

    3.2 入门案例

      在使用pinyin4J之前,需要导入相关的jar包,或者引入pinyin4J的依赖

            <!-- 引入pinyin4J的依赖 -->
            <dependency>
                <groupId>com.belerweb</groupId>
                <artifactId>pinyin4j</artifactId>
                <version>2.5.0</version>
            </dependency>

      编写测试代码:

    public class PinYin4jUtilsTest {
    
        @Test
        public void test1() {
            //河北省    石家庄市    桥西区
            String province = "河北省";
            String city = "石家庄市";
            String district = "桥西区";
            //简码---->>HBSJZQX
    
            province = province.substring(0, province.length() - 1); //河北
            city = city.substring(0, city.length() - 1); //石家庄
            district = district.substring(0, district.length() - 1); //桥西
    
            String info = province + city + district;
    
            String[] headByString = PinYin4jUtils.getHeadByString(info);
            String shorcode = StringUtils.join(headByString);
            System.out.println(shorcode);
    
            //城市编码---->>shijiazhuang
            String citycode = PinYin4jUtils.hanziToPinyin(city, "");
            System.out.println(citycode);
        }
    }

    3.3 修改RegionAction

    @Controller
    @Scope("prototype")
    public class RegionAction extends ActionSupport implements ModelDriven<Region> {
        private Region region;
    
        @Autowired
        private IRegionService regionService;
    
        // 属性驱动,接收上传的文件
        private File regionFile;
    
        public void setRegionFile(File regionFile) {
            this.regionFile = regionFile;
        }
    
        /**
         * 区域导入
         *
         * @return
         */
        public String importXls() throws IOException {
            List<Region> regionList = new ArrayList<>();
            //使用POI解析Excel文件
            HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(regionFile));
            //根据名称获得指定Sheet对象
            HSSFSheet hssfSheet = workbook.getSheet("Sheet1");
            //遍历标签页中所有的行
            for (Row row : hssfSheet) {
                int rowNum = row.getRowNum(); // 行号
                // 如果是标题行,结束本次循环,直接进入下一次循环
                if (rowNum == 0) {
                    continue;
                }
                String id = row.getCell(0).getStringCellValue();
                String province = row.getCell(1).getStringCellValue();
                String city = row.getCell(2).getStringCellValue();
                String district = row.getCell(3).getStringCellValue();
                String postcode = row.getCell(4).getStringCellValue();
                // 包装一个区域对象
                Region region = new Region(id, province, city, district, postcode, null, null);
    
                province = province.substring(0, province.length() - 1);
                city = city.substring(0, city.length() - 1);
                district = district.substring(0, district.length() - 1);
                String info = province + city + district;
                String[] headByString = PinYin4jUtils.getHeadByString(info);
                String shortcode = StringUtils.join(headByString);
                //城市编码---->>shijiazhuang
                String citycode = PinYin4jUtils.hanziToPinyin(city, "");
                region.setShortcode(shortcode);
                region.setCitycode(citycode);
    
                regionList.add(region);
            }
            // 批量保存
            regionService.saveBatch(regionList);
            return NONE;
        }
    
        @Override
        public Region getModel() {
            return region;
        }
    }

       查看数据库,这时候shortcode和citycode的数据也生成了

      

    四、使用POI导出页面数据

    4.1 页面调整

      

      为页面中导出按钮绑定事件

    // 导出按钮对应的处理函数
    function doExport(){
        // 发送请求,请求action,进行文件下载
        window.location.href = "subareaAction_exportXls.action"
    }

    4.2 服务端实现

      第一步:查询所有的分区数据

      第二步:使用POI将数据写到Excel文件中

      第三步:使用输出流进行文件下载

      /**
         * 分区数据导出功能
         * @throws IOException 
         */
        public String exportXls() throws IOException{
            //第一步:查询所有的分区数据
            List<Subarea> list = subareaService.findAll();
            
            //第二步:使用POI将数据写到Excel文件中
            //在内存中创建一个Excel文件
            HSSFWorkbook workbook = new HSSFWorkbook();
            //创建一个标签页
            HSSFSheet sheet = workbook.createSheet("分区数据");
            //创建标题行
            HSSFRow headRow = sheet.createRow(0);
            headRow.createCell(0).setCellValue("分区编号");
            headRow.createCell(1).setCellValue("开始编号");
            headRow.createCell(2).setCellValue("结束编号");
            headRow.createCell(3).setCellValue("位置信息");
            headRow.createCell(4).setCellValue("省市区");
            
            for (Subarea subarea : list) {
                HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);
                dataRow.createCell(0).setCellValue(subarea.getId());
                dataRow.createCell(1).setCellValue(subarea.getStartnum());
                dataRow.createCell(2).setCellValue(subarea.getEndnum());
                dataRow.createCell(3).setCellValue(subarea.getPosition());
                dataRow.createCell(4).setCellValue(subarea.getRegion().getName());
            }
            
            //第三步:使用输出流进行文件下载(一个流、两个头)
            
            String filename = "分区数据.xls";
            String contentType = ServletActionContext.getServletContext().getMimeType(filename);
            ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();
            ServletActionContext.getResponse().setContentType(contentType);
            
            //获取客户端浏览器类型
            String agent = ServletActionContext.getRequest().getHeader("User-Agent");
            filename = FileUtils.encodeDownloadFilename(filename, agent);
            ServletActionContext.getResponse().setHeader("content-disposition", "attachment;filename="+filename);
            workbook.write(out);
            return NONE;
        }

       

     参考:https://www.cnblogs.com/xiaobai1226/p/7507953.html

  • 相关阅读:
    Android--多线程之Handler
    webkit-transition-
    结构体直接赋值
    shell 俄罗斯方块 杂记
    debian 开启daytime等服务 "xinetd"
    Linux中 etc/init.d “服务"
    <iOS>关于Xcode上的Other linker flags
    多线程总结
    git的使用与分支管理
    -ios项目中安装和使用CocoaPods
  • 原文地址:https://www.cnblogs.com/yft-javaNotes/p/10353108.html
Copyright © 2011-2022 走看看