使用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

posted @ 2019-02-06 14:39  yi0123  阅读(628)  评论(0编辑  收藏  举报