Java实现批量导出导入数据及附件文件zip包

目录
  • 前言-应用场景
  • 一、导出ZIP包
    • 1. 列表数据导出到本地excel文件
    • 2. 下载附件信息
    • 3. 生成压缩文件(浏览器下载)
    • 4. 删除临时目录
  • 二、导入ZIP包
    • 1. 上传zip包,解压到临时目录
    • 2. 读取附件信息上传到文件服务器
    • 3. 读取Excel文件存入数据库
    • 4. 删除临时文件

前言-应用场景

某系统在不同单位使用时存在两套生产环境,他们的数据不是互通的,所以这些单位的上一级领导部门在统计数据的时候希望将A系统的数据和附件信息导出到一个压缩包里,然后把这个压缩包一键导入到B系统,这样B系统就包含了全部的数据,上级领导就能看到全部的业务信息,便于统计分析。

一、导出ZIP包

1. 列表数据导出到本地excel文件

        String path = profile + "/temp/" + DateUtils.dateTimeNow();
        File file = new File(path);
        if (file.mkdirs()) {
            System.out.println("文件夹创建成功!创建后的文件目录为:" + file.getPath());
        }
        //1. 输出Excel文件
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("sheet");
        String fileName="XX数据导出.xls";
        String savePath= file.getPath() + File.separator +fileName;
        OutputStream os = new FileOutputStream(savePath);
        //响应到客户端(即浏览器端直接弹出下载连接的方式)需要用response获取流
        //this.setResponseHeader(response, filename);
        //OutputStream os = response.getOutputStream();
        List<HashMap> dataList = new ArrayList<>();
        try{
            // 表头
            this.createExcelTitle(workbook, sheet);
            // 查询条件
            HashMap param = this.buildQueryParams(params);
            dataList = shareRegisterMapper.shareList(param);
            if (CollectionUtils.isEmpty(dataList)){
                return;
            }
            this.dealAssetData(dataList, sheet);
            // 处理子表数据
            this.dealAssetDetailData(dataList,workbook);
            workbook.write(os);
            os.flush();
            os.close();
        }catch(Exception e) {
            e.printStackTrace();

​​​​​​​        }finally {
            if (os != null) {
                os.flush();
                os.close();
            }
            workbook.close();
        }

2. 下载附件信息

在上一步生成的Excel文件路径下新建files文件夹,里面存放附件

public void downloadFile(List<HashMap> dataList) throws Exception {
    String urlPrefix = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
    String savePath = file.getPath() + File.separator + "/files";
        OutputStream os = null;
        InputStream is = null;
        int i=0;
        try {
            for (HashMap data : dataList) {
                if (data == null || data.get("FILES") == null){
                    continue;
                }
                List<ZsglFileEntity> entityList = new ArrayList<>();
                String[] fileArray = data.get("FILES").toString().split(",");
                List idList = Arrays.asList(fileArray);
                entityList.addAll(fileMapper.selectByIds(idList));
                if (CollectionUtils.isNotEmpty(entityList)){
                    for (ZsglFileEntity file : entityList){
                        if ( file.getFssFileId() == null){
                            continue;
                        }
                        String fileUrl = urlPrefix + "/fss/download/" + file.getFssFileId();
                        // 构造URL
                        URL url = new URL(fileUrl);
                        // 打开连接
                        URLConnection con = url.openConnection();
                        //设置请求超时为5s
                        con.setConnectTimeout(5 * 1000);
                        // 输入流
                        is = con.getInputStream();
                        File tempFile = new File(savePath + "/"+file.getFileName());
                        // 校验文件夹目录是否存在,不存在就创建一个目录
                        if (!tempFile.getParentFile().exists()) {
                            tempFile.getParentFile().mkdirs();
                        }
                        os = new FileOutputStream(tempFile);
                        is = con.getInputStream();
                        con.getHeaderFields();
                        IOUtils.copy(is, os);
                        System.out.println("下载完成");
                    }
                    entityList.clear();
                }
            }
        }catch (IOException e){
            System.err.println(e);
        }finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(os);
        }
    }

3. 生成压缩文件(浏览器下载)

        response.setCharacterEncoding("UTF-8");
        response.setContentType("multipart/form-data");
        response.setHeader("content-disposition", "attachment;filename=" + "XX数据导出.zip");
        ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
        try {
            File[] sourceFiles = file.listFiles();
            if (null == sourceFiles || sourceFiles.length < 1) {
                System.out.println("待压缩的文件目录:" + "里面不存在文件,无需压缩.");
            } else {
                for (int i = 0; i < sourceFiles.length;i++){
                    File srcFile = sourceFiles[i];
                    if (srcFile.isDirectory()){
                        File[] imageSourceFiles = srcFile.listFiles();
                        if (null == imageSourceFiles || imageSourceFiles.length < 1){
                            continue;
                        }
                        for (File imageFile : imageSourceFiles){
                            compress(zos,imageFile,srcFile.getName()+"/");
                        }
                    } else {
                        compress(zos,srcFile,"");
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if(null != zos) {
                    zos.close();
                }
            } catch (IOException e){
                e.printStackTrace();
            }
        }

其中的压缩方法如下:

public void compress(ZipOutputStream out,File sourceFile,String base) throws Exception
    {
        out.putNextEntry( new ZipEntry(base+sourceFile.getName()) );
        FileInputStream fos = new FileInputStream(sourceFile);
        BufferedInputStream bis = new BufferedInputStream(fos);
        int tag;
        System.out.println(base);
        //将源文件写入到zip文件中
        while((tag=bis.read())!=-1) {
            out.write(tag);
            out.flush();
        }
        out.closeEntry();
        bis.close();
        fos.close();
    }

4. 删除临时目录

public void deleteDirectory(File file) {
        File[] list = file.listFiles();  //无法做到list多层文件夹数据
        if (list != null) {
            for (File temp : list) {     //先去递归删除子文件夹及子文件
                deleteDirectory(temp);   //注意这里是递归调用
            }
        }
        if (!file.delete()) {     //再删除自己本身的文件夹
            logger.error("文件删除失败 : %s%n", file);
        }
    }

二、导入ZIP包

1. 上传zip包,解压到临时目录

这里开始想着在不解压的情况下读取里面的文件,结果没有走通。因为zip里面包含了子文件夹里面的附件信息需要解析。不解压直接解析文件适用于只需要解析zip包中第一层文件的场景,如果子文件夹下的文件也需要处理的话,最好解压后再处理。

public void unzip(ZipInputStream zipIn, String destDirectory) throws IOException {
        File destDir = new File(destDirectory);
        if (!destDir.exists()) {
            destDir.mkdirs();
        }
        ZipEntry entry = zipIn.getNextEntry();
        // 遍历Zip文件中的条目
        while (entry != null) {
            String filePath = destDirectory + File.separator + entry.getName();
            if (!entry.isDirectory()) {
                int index = entry.getName().indexOf("/");
                if (index > -1 && entry.getName().length() > index){
                    File tempFile = new File(destDirectory + File.separator +entry.getName().substring(0,index));
                    if (!tempFile.exists()){
                        tempFile.mkdir();
                    }
                }
                File checkFile = new File(filePath);
                if (!checkFile.exists()) {
                    checkFile.createNewFile();// 创建目标文件
                }
                // 如果条目是文件直接解压
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
                byte[] bytesIn = new byte[1024];
                int read = 0;
                while ((read = zipIn.read(bytesIn)) != -1) {
                    bos.write(bytesIn, 0, read);
                }
                bos.close();
            } else {
                File dir = new File(filePath);
                if (!dir.exists()){
                    dir.mkdirs();
                }
            }
            zipIn.closeEntry();
            entry = zipIn.getNextEntry();
        }
        zipIn.close();
    }

这里解压遇到了一个问题,之前导出生成的zip包直接导入没问题,但是我把导出的包手动解压后修改了部分数据重新压缩后再导入报错:ZipInputStream解压远程文件报错,java.lang.IllegalArgumentException: MALFORMED

原因:文件名含有中文,zip解析出错

解决方案,如下行代码,在生成ZipInputStream的时候指定编码格式。

ZipInputStream zis = new ZipInputStream(new BufferedInputStream(inputStream), Charset.forName(“GBK”));

2. 读取附件信息上传到文件服务器

public List<HashMap> readLocalFile() throws Exception {
        File file= new File(destDirectory+"/files");
        List<HashMap> fssList = new ArrayList<>();
        if (file.exists()) {
            File[] sourceFiles = file.listFiles();
            if (null == sourceFiles || sourceFiles.length < 1) {
                System.out.println(file.getName()+"目录里面不存在文件,无需处理.");
                return fssList;
            } else {
                for (int i = 0; i < sourceFiles.length;i++){
                    File srcFile = sourceFiles[i];
                    FileItemFactory factory = new DiskFileItemFactory(16, null);
                    FileItem item = factory.createItem(srcFile.getName(), "text/plain", true, srcFile.getName());
                    int bytesRead = 0;
                    byte[] buffer = new byte[8192];
                    try {
                        FileInputStream fis = new FileInputStream(srcFile);
                        OutputStream os = item.getOutputStream();
                        while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                            os.write(buffer, 0, bytesRead);
                        }
                        os.close();
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    MultipartFile mfile = new CommonsMultipartFile(item);
                    AjaxResult fileResult = this.fssFileService.uploadFile(mfile);
                    String filePath = fileResult.get("url") == null ? "" : fileResult.get("url").toString();
                    if (fileResult.get("fileId") != null){
                        HashMap tempMap = new HashMap();
                        String fileId = this.fileService.saveFileInfo(fileResult.get("fileId").toString(),mfile, filePath, "");
                        tempMap.put(srcFile.getName(), fileId);
                        fssList.add(tempMap);
                    }
                }
            }
        }
        return fssList;
    }

注意:这里有个小难点就是File转换成MultipartFile的方法,因为项目中已经有的上传文件是MultipartFile格式的,转换一下就不用在实现一遍上传方法了。

3. 读取Excel文件存入数据库

我是用EasyExcel导入Excel文件的,代码很简单,需要注意用EasyExcel导入的Excel文件如果包含多个sheet页,需要写多个导入监听文件。

4. 删除临时文件

这一步实现方法跟导出时相同,去掉临时文件。

以上就是Java实现批量导出导入数据及附件文件zip包的详细内容,更多关于Java导出导入数据的资料请关注我们其它相关文章!

(0)

相关推荐

  • java批量导入导出文件的实例分享(兼容xls,xlsx)

    一.介绍 利用java实现文件的导入导出数据库,目前在大部分系统中是比较常见的功能了,今天写个小demo来理解其原理,没接触过的同学也可以看看参考下. 目前我所接触过的导入导出技术主要有POI和iReport,poi主要作为一些数据批量导入数据库,iReport做报表导出.另外还有jxl类似poi的方式,不过貌似很久没跟新了,2007之后的office好像也不支持,这里就不说了. 二.POI使用详解 2.1 什么是Apache POI? Apache POI是Apache软件基金会的开放源码函式

  • java实现Excel的导入、导出

    一.Excel的导入 导入可采用两种方式,一种是JXL,另一种是POI,但前者不能读取高版本的Excel(07以上),后者更具兼容性.由于对两种方式都进行了尝试,就都贴出来分享(若有错误,请给予指正) 方式一.JXL导入  所需jar包 JXL.jar publicstaticList<PutStorageInfo> readExcelByJXL(String filePath){ List<PutStorageInfo> infoList =newArrayList<Put

  • java实现文件导入导出

    文件导入导出必须代码 ExportExcel.java /** * Copyright © 2012-2014 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved. */ package com.thinkgem.jeesite.common.utils.excel; import java.io.FileNotFoundException; import j

  • java实现Excel的导入导出

    本文实例为大家分享了java实现Excel导入导出的具体代码,供大家参考,具体内容如下 一.Excel读写技术 区别: 二.jxl读写基础代码 1.从数据库将数据导出到excel表格 public class JxlExcel { public static void main(String[] args) { //创建Excel文件 String[] title= {"姓名","课程名","分数"}; File file=new File(&q

  • Java实现Excel导入导出数据库的方法示例

    本文实例讲述了Java实现Excel导入导出数据库的方法.分享给大家供大家参考,具体如下: 由于公司需求,想通过Excel导入数据添加到数据库中,而导入的Excel的字段是不固定的,使用得通过动态创建数据表,每个Excel对应一张数据表,怎么动态创建数据表,可以参考前面一篇<java使用JDBC动态创建数据表及SQL预处理的方法>. 下面主要讲讲怎么将Excel导入到数据库中,直接上代码:干货走起~~ ExcellToObjectUtil 类 主要功能是讲Excel中的数据导入到数据库中,有几

  • Java实现批量导出导入数据及附件文件zip包

    目录 前言-应用场景 一.导出ZIP包 1. 列表数据导出到本地excel文件 2. 下载附件信息 3. 生成压缩文件(浏览器下载) 4. 删除临时目录 二.导入ZIP包 1. 上传zip包,解压到临时目录 2. 读取附件信息上传到文件服务器 3. 读取Excel文件存入数据库 4. 删除临时文件 前言-应用场景 某系统在不同单位使用时存在两套生产环境,他们的数据不是互通的,所以这些单位的上一级领导部门在统计数据的时候希望将A系统的数据和附件信息导出到一个压缩包里,然后把这个压缩包一键导入到B系

  • Java使用easyExcel导出excel数据案例

    easyExcel简介: Java领域解析.生成Excel比较有名的框架有Apache poi.jxl等.但他们都存在一个严重的问题就是非常的耗内存.如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc. easyExcel是阿里巴巴开源的一个excel处理框架,以使用简单.节省内存著称. easyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理 easyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据

  • Java使用POI导出大数据量Excel的方法

    今天需要写一个导出的Excel的功能,但是发现当数据量到3万条时,列数在23列时,内存溢出,CPU使用100%,测试环境直接炸掉.在本地测试时发现,导出3000条左右的数据的时候,堆内存瞬间升高500M左右.然后发现了 SXSSFWorkbook 这个类. 简介 SXSSFWorkbook 需要 poi-ooxml 包 3.8 及以上开始支持,我这边适使用的是 3.9 版本,本质是一个 XSSFWorkbook 类( Excel2007 ),它使用的方式是采用 硬盘空间 来大幅降低 堆内存 的占

  • C#导出GridView数据到Excel文件类实例

    本文实例讲述了C#导出GridView数据到Excel文件类.分享给大家供大家参考.具体如下: 这段C#代码自定义了一个封装类,用于将GridView数据导出到Excel文件 using System; using System.Web; using System.Web.UI; using System.IO; using System.Web.UI.WebControls; namespace DotNet.Utilities { public class ExportExcel { pro

  • C#实现导出List数据到xml文件的方法【附demo源码下载】

    本文实例讲述了C#实现导出List数据到xml文件的方法.分享给大家供大家参考,具体如下: C#导出List数据到xml文件,这里主要用到的是: XmlSerializer 类 (System.Xml.Serialization) 将对象序列化到 XML 文档中和从 XML 文档中反序列化对象.XmlSerializer 使您得以控制如何将对象编码到 XML 中. 实体类代码: /// <summary> /// 用户实体类 /// /// 注意:类的访问修饰符必须是:public,否则会出现

  • php使用指定编码导出mysql数据到csv文件的方法

    本文实例讲述了php使用指定编码导出mysql数据到csv文件的方法.分享给大家供大家参考.具体实现方法如下: <?php /* * PHP code to export MySQL data to CSV * * Sends the result of a MySQL query as a CSV file for download * Easy to convert to UTF-8. */ /* * establish database connection */ $conn = mysq

  • python批量导出导入MySQL用户的方法

    数据库迁移(A -> B),需要把用户也迁移过去,而用户表(mysql.user)有上百个用户.有2种方法进行快速迁移:1,在同版本的条件下,直接备份A服务器的mysql数据库,还原到B服务器.2,要是不同版本的数据(5.1 -> 5.5),很可能mysql数据库下面的一些表结构,甚至表数据的默认值都不一样,按照1的方法进行迁移,虽然最后也是可以正常访问,但是还是有些不太放心,很可能会影响到了B服务器上的MySQL,这样就需要用命令行来生成帐号了,这样是最安全和放心的.下面用python脚本来

  • PHP导出MySQL数据到Excel文件(fputcsv)

    这里的方法是利用fputcsv写CSV文件的方法,直接向浏览器输出Excel文件. 复制代码 代码如下: // 输出Excel文件头,可把user.csv换成你要的文件名 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="user.csv"'); header('Cache-Control: max-age=0'); // 从数据库中获取

  • MySQL数据库迁移快速导出导入大量数据

    数据库迁移是我们经常可遇到的问题,对于少量的数据,迁移基本上不会有什么问题.生产环境中,有以下情况需要做迁移工作: 磁盘空间不够.比如一些老项目,选用的机型并不一定适用于数据库.随着时间的推移,硬盘很有可能出现短缺: 业务出现瓶颈.比如项目中采用单机承担所有的读写业务,业务压力增大,不堪重负.如果 IO 压力在可接受的范围,会采用读写分离方案: 机器出现瓶颈.机器出现瓶颈主要在磁盘 IO 能力.内存.CPU,此时除了针对瓶颈做一些优化以外,选择迁移是不错的方案: 项目改造.某些项目的数据库存在跨

  • MySQL如何快速导入数据

    前言: 日常学习和工作中,经常会遇到导数据的需求.比如数据迁移.数据恢复.新建从库等,这些操作可能都会涉及大量数据的导入.有时候导入进度慢,电脑风扇狂转真的很让人崩溃,其实有些小技巧是可以让导入更快速的,本篇文章笔者会谈一谈如何快速的导入数据. 注:本篇文章只讨论如何快速导入由逻辑备份产生的SQL脚本,其他文件形式暂不讨论. 1.尽量减小导入文件大小 首先给个建议,导出导入数据尽量使用MySQL自带的命令行工具,不要使用Navicat.workbench等图形化工具.特别是大数据量的时候,用My

随机推荐