基于SpringBoot后端導出Excel文件的操作方法
更新時間:2024年02月06日 10:07:55 作者:小雅痞
這篇文章給大家介紹了基于SpringBoot后端導出Excel文件的操作方法,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
后端導出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對象這一步應該是個性化的。
- 中文的文件名需要經(jīng)過編碼,不然傳到前端會亂碼
- 工具類的源碼放在文末
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); }
前端下載
后端導出失敗和成功返回的內(nèi)容類型不同,因此需要分別判斷。
- 返回的是json類型的錯誤信息:
- 只有導出成功,才是文件流:
<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 = fileName a.target = '_blank' a.style.display = 'none' document.body.appendChild(a) a.click() a.remove() }
以上就是基于SpringBoot后端導出Excel文件的操作方法的詳細內(nèi)容,更多關(guān)于SpringBoot后端導出Excel的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java Socket聊天室編程(一)之利用socket實現(xiàn)聊天之消息推送
這篇文章主要介紹了Java Socket聊天室編程(一)之利用socket實現(xiàn)聊天之消息推送的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09Spring中@Transactional(rollbackFor=Exception.class)屬性用法介紹
這篇文章介紹了Spring中@Transactional(rollbackFor=Exception.class)屬性的用法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-12-12Java 將文件轉(zhuǎn)為字節(jié)數(shù)組知識總結(jié)及實例詳解
這篇文章主要介紹了Java 將文件轉(zhuǎn)為字節(jié)數(shù)組實例詳解的相關(guān)資料,需要的朋友可以參考下2016-12-12