导入导出(excel格式/压缩包格式导出至response、excel导入)

news/2024/7/21 7:35:04 标签: excel, java

目录

  • 导出
    • 一、excel格式导出至response
      • 1、List<对象>导出
      • 2、json对象不固定列导出
    • 二、压缩包格式导出至response
      • 使用Hutool工具简化代码
  • 导入
    • 一、对象导入
    • 二、不固定列导入


导出

excelresponse_4">一、excel格式导出至response

1、List<对象>导出

java">Map<String, String> headerAlias = new LinkedHashMap<String, String>();
headerAlias.put("数据列一对象英文名称", "显示的中文名称");
... // 

BigExcelWriter excelWriter = new BigExcelWriter();
excelWriter.setHeaderAlias(headerAlias);
excelWriter.write(list); //  List<对象> list 是数据
if (null != response) {
    // 下边两行任取一行都可以
    response.addHeader("Content-Type", "application/vnd.ms-excel;charset=UTF-8");
    // response.addHeader("Content-Type", "application/octet-stream");
    response.addHeader("Content-Disposition", excelWriter.getDisposition("excel表名", StandardCharsets.UTF_8));
}
excelWriter.flush(response.getOutputStream(), true);
excelWriter.close();

2、json对象不固定列导出

java">// swagger无法测试
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse(); // 获取response对象

List<List<String>> resultListList = new ArrayList<>(); // 用于模拟excel
List<String> resultHeadList = new ArrayList<>(); // excel表头
resultHeadList.add("NAME");
... // 这里是固定的确定的列

for (int j = 0; j < jsonObj.size(); j++) {
    JSONArray jsonArray = jsonObj.getJSONArray("num" + j);
    List<String> resultList = new ArrayList<>(); // 模拟excel一行
    if (j == 0) { // 第一行
        resultList.add("固定列的相同取值");
        ... // 固定列处理
    } else { // 其余行
        resultList.add("");
        ... // 固定列处理
    }
    for (int i = 0; i < jsonArray.size(); i++) {
        JSONObject obj = jsonArray.getJSONObject(i);
        String name = StrUtil.trimToEmpty(obj.getStr("name"));
        String value = StrUtil.trimToEmpty(obj.getStr("value"));
        if (j == 0) {
            resultHeadList.add(name); // 表头增加相应名称
        }
        resultList.add(value);
    }
    resultListList.add(resultList);
}
resultListList.add(0, resultHeadList);
BigExcelWriter excelWriter = new BigExcelWriter();
excelWriter.write(resultListList);
if (null != response) {
    // 下边两行任取一行都可以
    response.addHeader("Content-Type", "application/vnd.ms-excel;charset=UTF-8");
    // response.addHeader("Content-Type", "application/octet-stream");
    response.addHeader("Content-Disposition", excelWriter.getDisposition("excel表名", StandardCharsets.UTF_8));
}
excelWriter.flush(response.getOutputStream(), true);
excelWriter.close();

二、压缩包格式导出至response

java">// 多个数据逗号分隔 String ->String[] 正则表达式:[,;,;:\\s]+
String[] fileUrlArray = Arrays.stream(StrUtil.trimToEmpty(request.getParameter("fileUrl")).replaceAll([,;,;:\\s]+, ",").replaceAll("^,|,$", "").split(","))
    .filter(StrUtil::isNotBlank).distinct().toArray(String[]::new);
// String[] 转换成 List 也仅仅用于 fileUrlSuffixMap 中快捷获得某一元素的下标 fileUrlList.indexOf(m)
List<String> fileUrlList = new ArrayList<>(fileUrlArray.length);
Collections.addAll(fileUrlList, fileUrlArray);

List<String> suffixList = Arrays.stream(fileUrlArray).map(m -> m.substring(m.lastIndexOf("."))).collect(Collectors.toList()); // 图片后缀名
Map<String, String> fileUrlSuffixMap = Arrays.stream(fileUrlArray).collect(Collectors.toMap(m -> m, m -> suffixList.get(fileUrlList.indexOf(m)))); // 图片url和后缀名map

String sku = StrUtil.trimToEmpty(request.getParameter("sku")); // 仅仅用于压缩包命名
String rootPath = request.getRealPath("/");
File file = new File(rootPath + "temp_download");
if (!file.exists()) {
    file.mkdir();
}
Arrays.stream(fileUrlArray).forEach(m -> HttpUtil.downloadFile(m,FileUtil.file(new File(rootPath + "temp_download" + 
                                                                                        File.separator + m.substring(m.lastIndexOf("/") + 1, m.lastIndexOf(".")) + fileUrlSuffixMap.get(m)))));

try {
    File zipFile = null;
    zipFile = new File(rootPath + "temp_download" + "/" + sku + ".zip");
    FileOutputStream zipFos = new FileOutputStream(zipFile);
    ArchiveOutputStream archOut = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, zipFos);
    ZipArchiveOutputStream zos = (ZipArchiveOutputStream) archOut;
    for (int i = 0; i < fileUrlArray.length; i++) {
        String ele = fileUrlArray[i];
        File imageFile = new File(rootPath + "temp_download" + "/" + ele.substring(ele.lastIndexOf("/") + 1, ele.lastIndexOf(".")) + suffixList.get(i));
        ZipArchiveEntry zipEntry = new ZipArchiveEntry(imageFile, imageFile.getName());
        zos.putArchiveEntry(zipEntry);
        zos.write(FileUtils.readFileToByteArray(imageFile));
        if (imageFile.exists()) {
            imageFile.delete();
        }
    }
    zos.closeArchiveEntry();
    zos.flush();
    zos.close();
    OutputStream out = null;
    out = response.getOutputStream();
    response.reset();
    response.setHeader("Content-Disposition", "attachment;filename=" + new String((sku + ".zip").getBytes("GB2312"), "ISO-8859-1"));
    response.setContentType("application/octet-stream; charset=utf-8");
    response.setCharacterEncoding("UTF-8");
    out.write(FileUtils.readFileToByteArray(zipFile));
    out.flush();
    out.close();
    if (zipFile.exists()) {
        zipFile.delete();
    }
    if (file.exists()) {
        file.delete();
    }
} catch (Exception e) {
    e.printStackTrace();
}

使用Hutool工具简化代码

java">// 输出到内存里面
String[] fileArray = fileStr.split(",");
try {
    AtomicInteger atomicAdd = new AtomicInteger(); // 文件大小累加器
    List<String> fileName = CollUtil.list(false); // 文件名
    InputStream[] ins = Arrays.stream(fileArray).map(url -> {
        byte[] bytes = HttpUtil.downloadBytes(url); // 上传到内存中
        fileName.add(url.substring(url.lastIndexOf("/") + 1)); // 文件名
        atomicAdd.addAndGet(bytes.length);
        return new ByteArrayInputStream(bytes);
    }).toArray(InputStream[]::new);

    ByteArrayOutputStream byteStream = new ByteArrayOutputStream(atomicAdd.intValue());
    ZipUtil.zip(byteStream, fileName.toArray(new String[0]), ins); // 参数:目标流、流数据在压缩文件中的路径或文件名、要压缩的
    response.setHeader("Content-Disposition", "attachment;filename=" + sku + ".zip");
    response.setContentType("application/octet-stream; charset=utf-8");

    OutputStream out = response.getOutputStream();
    out.write(byteStream.toByteArray());
    out.flush();
    out.close();
} catch (Exception e) {
    e.printStackTrace();
}

导入

一、对象导入

java">excelList = excelReader.readAll(....class);

二、不固定列导入

java">if (file.isEmpty()) {
    return failure("文件为空");
}
InputStream inputStream = null;
Boolean result = false; // 修改成功标志
List<Map<String,Object>> excelList = new ArrayList<>();
Obj obj = new Obj(); // excel对应的对象,其中一个字段存json数据
try {
    inputStream = file.getInputStream();
    ExcelReader excelReader = ExcelUtil.getReader(inputStream);
    // 检验固定列是否正确
    if (!"NAME".equals(excelReader.readRow(0).get(0))) {
        return ...
    } 
    // else if ... 其余固定列的检验
    
    // 读取为Map列表,默认第一行为标题行,Map中的key为标题,value为标题对应的单元格值。
    excelList = excelReader.readAll();
    // 两种方式
    // excelReader.readRow(0).get(0)、excelList.get(0).get("NAME")
    obj.setName(excelList.get(0).get("NAME").toString());
    JSONObject jsonObj = new JSONObject();
    for (int i = 0; i < excelList.size(); i++) {
        JSONArray jsonArray = new JSONArray();
        Map<String, Object> oneObjMap = excelList.get(i);
        for (Map.Entry<String, Object> entry : oneObjMap.entrySet()) {
            JSONObject jsonObject = new JSONObject();
            String key = entry.getKey();
            Object value = entry.getValue();
            if ("NAME".equals(key) || ...) { // 遇到固定列则跳过
                continue;
            }
            jsonObject.set("name", key);
            jsonObject.set("value", value);
            jsonArray.add(jsonObject);
        }
        jsonObj.set("num" + i, jsonArray);
    }
    obj.setJsonObj(jsonObj.toString());
} catch (Exception e) {
    e.printStackTrace();
}

http://www.niftyadmin.cn/n/5302134.html

相关文章

并发编程下的集合:数组寻址、LinkedList、HashMap、ConcurrentHashMap

数组如何寻址 a[n]起始地址(n*字节数) 译&#xff1a;a[2]100(2*4) 2为下标、4为int类型字段占四个字节 LinkedList LinkedList为双向链表结构&#xff0c;链表结构又分为单向、双向、以及循环。 // 双向链表 private static class Node<E> {E item;Node<E> nex…

【AIGC摄影构图prompt】与重不同的绘制效果,解构主义+优美连拍提示效果

提取关键词构图&#xff1a; 激进解构主义 在prompt中&#xff0c;激进解构主义的画面效果可能是一种颠覆传统和权威的视觉呈现。这种画面可能以一种极端或激烈的方式表达对现有社会结构和观念体系的批判和质疑。 具体来说&#xff0c;这种画面效果可能包括&#xff1a; 破…

VINS-MONO拓展1----手写后端求解器,LM3种阻尼因子策略,DogLeg,构建Hessian矩阵

文章目录 0. 目标及思路1. 非线性优化求解器2. 基于VINS-MONO的Marginalization框架构建Hessian矩阵2.1 estimator.cpp移植2.2 solve.cpp/preMakeHessian()2.3 solve.cpp/makeHessian() 3. solve.cpp/solveLinearSystem()求解正规方程4. 更新状态5. 迭代求解6. EVO评估结果7. 待…

数据分析基础之《numpy(6)—IO操作与数据处理》

了解即可&#xff0c;用panads 一、numpy读取 1、问题 大多数数据并不是我们自己构造的&#xff0c;而是存在文件当中&#xff0c;需要我们用工具获取 但是numpy其实并不适合用来读取和处理数据&#xff0c;因此我们这里了解相关API&#xff0c;以及numpy不方便的地方即可 2…

C# 验证文件共享模式下的多线程文件写入

目录 写在前面 代码实现 调用示例 加锁的情况 不加锁的情况 总结 写在前面 原以为设置了文件共享模式为允许随后写入(FileShare.Write)&#xff0c;就可以实现多线程下的正常写入操作&#xff0c;实际情况是使用该模式后不会报线程独占问题&#xff0c;但是写入的内容是…

DNS主从服务器、转发(缓存)服务器

一、主从服务器 1、基本含义 DNS辅助服务器是一种容错设计&#xff0c;考虑的是一旦DNS主服务器出现故障或因负载太重无法及时响应客户机请求&#xff0c;辅助服务器将挺身而出为主服务器排忧解难。辅助服务器的区域数据都是从主服务器复制而来&#xff0c;因此辅助服务器的数…

基于springboot+vue零食商城管理系统

摘要 基于Spring Boot Vue的零食商城管理系统是一项集成了先进技术的电商解决方案。此系统以Spring Boot为后端框架&#xff0c;结合Vue.js构建前端&#xff0c;致力于实现零食商城的高效管理和用户友好的界面体验。首先&#xff0c;Spring Boot框架作为后端核心&#xff0c;为…

EBU7140 Security and Authentication(四)网络安全,邮件安全,威胁

B4 更偏向应用层。 Web Security 主要面临的威胁还是四种&#xff1a;认证问题&#xff0c;保密问题&#xff0c;数据完整性问题&#xff0c;还有拒绝服务问题&#xff08;比如 DDOS&#xff1f;疯狂发送信息来阻塞服务器&#xff0c;干扰正常服务功能&#xff09;。 使用的…