基于SpringBoot的后端导出Excel文件

后端导出Excel,前端下载。

系列文章指路👉

系列文章-基于SpringBoot3创建项目并配置常用的工具和一些常用的类

文章目录

  • 后端导出Excel
    • 引入依赖
    • 写入响应
  • 前端下载
    • 后端导出失败和成功返回的内容类型不同,因此需要分别判断。
  • 工具类
    • ServletUtils.java
    • FileUtils.java
    • file.js

后端导出Excel

引入依赖

poi 操作xls,doc…;poi-ooxml操作xlsx,docx…
⚠️使用的版本比较新,可能跟老版本有些写法不兼容

        <!-- poi and poi-ooxml --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.2</version></dependency>

写入响应

  • 生成Workbook对象这一步应该是个性化的。
  • 中文的文件名需要经过编码,不然传到前端会乱码
  • 工具类的源码放在文末
    public Object export(String orderNum) {// 1. 生成Excel Workbook对象XSSFWorkbook workbook = initWorkbook(orderNum);HttpServletResponse rep = ServletUtils.getResponse();String errMessage;String fileName = "超市购进单-"+ DateUtil.today() + ".xlsx";if(Objects.isNull(rep)){throw new NullPointerException("HttpServletResponse 为空");}try {// 2. 将HSSFWorkbook文件写入到响应输出流中,供前端下载FileUtils.writeToResponse(workbook, fileName, rep);return null;}catch (IOException ioe){log.error("OrderServiceImpl export --- 导出过程中遇到输入输出异常: {}" ,ioe.toString());errMessage = "导出过程中遇到输入输出异常" + ioe;} catch (Exception e){log.error("OrderServiceImpl export --- 导出过程中遇到其他异常: {}" ,e.toString());errMessage = "导出过程中遇到其他异常:" + e;}return BaseResult.fail(errMessage);}

前端下载

后端导出失败和成功返回的内容类型不同,因此需要分别判断。

  • 返回的是json类型的错误信息:
    res1
  • 只有导出成功,才是文件流:res2
<template><h1>Excel导出测试</h1><p style="margin-top: 40px"><a-space><a-button type="primary" :icon="h(DownloadOutlined)" @click="downloadFile">下载Excel</a-button></a-space></p>
</template>
<script setup>
import {h} from 'vue';
import {DownloadOutlined} from '@ant-design/icons-vue';
import {UploadOutlined} from '@ant-design/icons-vue';
import {message} from "ant-design-vue";
import http from "@/utils/axios/index.js";
import {downloadFile as downer} from "@/utils/file.js";function downloadFile() {http.get('/manage/order/export', {params: {orderNum: '000001'},responseType: 'blob'}).then(resp => {if (resp.data.type === 'application/json') {// 失败了才会返回json类型const reader = new FileReader();reader.readAsText(resp.data, 'utf-8');reader.onload = () => {const result = JSON.parse(reader.result)message.error(`Error: ${result.message}`);};} else {downer(resp)}}).catch(err => {message.error('导出失败:' + err)console.log(err)})
}
</script>

工具类

ServletUtils.java

package com.ya.boottest.utils.servlet;import com.alibaba.fastjson.JSON;
import com.ya.boottest.utils.result.BaseResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import java.io.IOException;
import java.util.Objects;/*** <p>* Servlet 工具类* </p>** @author Ya Shi* @since 2024/1/4 14:29*/@Slf4j
public class ServletUtils {/*** 获取Attributes** @return ServletRequestAttributes*/public static ServletRequestAttributes getRequestAttributes() {RequestAttributes attributes = RequestContextHolder.getRequestAttributes();if(Objects.isNull(attributes)){log.error("ServletUtils 获取到的RequestAttributes为空");throw new RuntimeException("ServletUtils 获取到的RequestAttributes为空");}return (ServletRequestAttributes) attributes;}/*** 获取request** @return HttpServletRequest*/public static HttpServletRequest getRequest() {return getRequestAttributes().getRequest();}/*** 获取session** @return HttpSession*/public static HttpSession getSession() {return getRequest().getSession();}/*** 获取response** @return HttpServletResponse*/public static HttpServletResponse getResponse() {return getRequestAttributes().getResponse();}   
}

FileUtils.java

package com.ya.boottest.utils.file;import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;/*** <p>*  文件util* </p>** @author Ya Shi* @since 2023/8/11 11:58*/
@Slf4j
public class FileUtils {/*** 将HSSFWorkbook文件写入到响应输出流中,供前端下载* @param workbook 文件对象* @param fileName 文件名* @param response HttpServletResponse响应* @throws IOException IO异常*/public static void writeToResponse(XSSFWorkbook workbook, String fileName, HttpServletResponse response) throws IOException{try {response.setHeader("Content-Disposition", "attachment;filename=" + processFileName(fileName));response.setContentType("application/octet-stream; charset=utf-8");response.setCharacterEncoding("utf-8");ByteArrayOutputStream bos = new ByteArrayOutputStream();workbook.write(bos);byte[] bytes = bos.toByteArray();OutputStream outData = response.getOutputStream();outData.write(bytes);outData.flush();} catch (IOException e) {log.error("FileUtil writeToResponse workbook写入响应失败-----> " + e);throw e;}}/*** 对要下载的文件的名称进行编码,防止中文乱码问题。** @param fileName 文件名* @return String*/public static String processFileName(String fileName) throws IOException {String codedFilename;String prefix = fileName.lastIndexOf(".") != -1 ? fileName.substring(0, fileName.lastIndexOf(".")) : fileName;String extension = fileName.lastIndexOf(".") != -1 ? fileName.substring(fileName.lastIndexOf(".")) : "";String name = java.net.URLEncoder.encode(prefix, StandardCharsets.UTF_8);if (name.lastIndexOf("%0A") != -1) {name = name.substring(0, name.length() - 3);}int limit = 150 - extension.length();if (name.length() > limit) {name = java.net.URLEncoder.encode(prefix.substring(0, Math.min(prefix.length(), limit / 9)), StandardCharsets.UTF_8);if (name.lastIndexOf("%0A") != -1) {name = name.substring(0, name.length() - 3);}}name = name.replaceAll("[+]", "%20");codedFilename = name + extension;log.info("FileUtil processFileName codedFilename-----> " + codedFilename);return codedFilename;}
}

file.js

export function downloadFile(resp) {const tmp = 'filename='const contentDisposition = decodeURIComponent(resp.headers['content-disposition'])const fileName = contentDisposition.substring(contentDisposition.indexOf(tmp) + tmp.length)const contentType = resp.headers['content-type']const blob = new Blob([resp.data], {type: contentType})let a = document.createElement('a')a.href = URL.createObjectURL(blob)a.download = fileNamea.target = '_blank'a.style.display = 'none'document.body.appendChild(a)a.click()a.remove()
}

明月别枝惊鹊,清风半夜鸣蝉。

—— 宋朝 · 辛弃疾《 西江月 夜行黄沙道中 》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/453971.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第97讲:MHA高可用集群模拟主库故障以及修复过程

文章目录 1.分析主库故障后哪一个从库会切换为主库2.模拟主库故障观察剩余从库的状态2.1.模拟主库故障2.3.当前主从架构 3.修复故障的主库3.1.修复主库3.2.当前主从架构3.3.恢复MHA 1.分析主库故障后哪一个从库会切换为主库 在模拟MHA高可用集群主库故障之前&#xff0c;我们先…

外汇天眼:黑平台CCF Markets专坑华人,交钱才能出金!

一般来说&#xff0c;投资者在交易期间或多或少会都会遇到无法出金的情况&#xff0c;而平台面对这种情况&#xff0c;都会告知投资者理由&#xff0c;当然理由是五花八门的&#xff0c;有真亦有假。而有些理由一看就能判断出真假&#xff0c;如果平台方能说出这些理由&#xf…

【C语言/基础梳理/期末复习】动态内存管理(附思维导图)

目录 一、为什么要有动态内存分配 &#xff08;1&#xff09;我们已经掌握的内存方式的特点 &#xff08;2&#xff09;需求 二、malloc和free 2.1.malloc 2.1.1函数原型 2.1.2函数使用 2.1.3应用示例​编辑 2.2free 2.2.1函数原型 2.2.2函数使用 三、calloc和reallo…

【IC设计】Windows下基于IDEA的Chisel环境安装教程(图文并茂)

Chisel环境安装教程 第一步 安装jdk&#xff0c;配置环境变量第二步 安装sbt&#xff0c;不用配置环境变量第三步 安装idea社区版第四步 离线安装scala的idea插件第五步 配置sbt换源1.切换目录2.创建repositories文件3.配置sbtconfig.txt文件 第六步 使用chisel-tutorial工程运…

mac下载工具:JDownloader 2 for Mac 中文版

JDownloader是一款开源的下载管理工具&#xff0c;主要使用Java编程语言开发&#xff0c;因此它能够在支持Java的操作系统上运行&#xff0c;包括Windows、Linux和Mac OS。这款软件专门为那些需要通过网盘下载文件的用户提供便利&#xff0c;它支持众多流行的网盘服务&#xff…

静态路由与策略路由

文章目录 概要静态路由策略路由区别分析使用场景 概要 静态路由、策略路由 静态路由 静态路由是网络管理员手动配置的路由。 策略路由 策略路由则是根据数据包的具体内容&#xff0c; 如源地址、目标地址等信息&#xff0c;进行特定的路由选择。 区别分析 通俗理解 静态…

Sui上TVL突破5亿美元,位列DeFi榜单前十名和最活跃链前五名

2023年Sui上DeFi协议迅速增长&#xff0c;2024年这一势头仍在继续&#xff0c;根据DeFiLlama报告Sui上TVL近期超过5亿美元。在不到一年的时间里就达到这个金额&#xff0c;得益于Sui的突破性指标&#xff0c;比如其峰值TPS接近6,000。 Sui TVL突破5亿美元&#xff0c;登上DeFi…

ROS从入门到精通4-1:Docker安装与常用命令总结

目录 0 专栏介绍1 Docker与机器人应用2 Docker安装步骤3 Docker常用命令3.1 创建与启动容器3.2 暂停与删除容器3.3 容器文件拷贝3.4 构建镜像与上下文 0 专栏介绍 本专栏旨在通过对ROS的系统学习&#xff0c;掌握ROS底层基本分布式原理&#xff0c;并具有机器人建模和应用ROS进…

AMH面板如何安装与公网远程访问本地面板界面

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

互联网医院|互联网医院平台让医疗更智慧更容易

近年来&#xff0c;互联网医院在我国的应用范围不断扩大。然而&#xff0c;仍有许多人和医疗机构对线上问诊小程序的推广持保留态度&#xff0c;认为其应用效果不佳、覆盖范围有限。那么&#xff0c;我们应如何充分利用互联网医院系统&#xff0c;让线上医疗发挥更大的优势呢&a…

【Spring】Spring 对 Ioc 的实现

一、Ioc 控制反转 控制反转是一种思想 控制反转是为了降低程序耦合度&#xff0c;提高程序扩展力&#xff0c;达到 OCP 原则&#xff0c;达到 DIP 原则 控制反转&#xff0c;反转的是什么&#xff1f; 将对象的创建权利交出去&#xff0c;交给第三方容器负责 将对象和对象之…

什么是跨境电商?跨境电商与api的关系是什么?

什么是跨境电商&#xff1f; 跨境电商是指通过互联网平台进行国际贸易的商业模式。它允许消费者在不同国家之间购买和销售商品&#xff0c;打破了传统贸易的地域限制&#xff0c;为消费者提供了更多选择和便利。 什么是跨境电商API&#xff1f; 跨境电商API通常指的是应用程…