news 2026/8/3 14:03:23

springboot controller返回的是HttpServletResponse成功返回excel文件流,失败就返回失败参数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
springboot controller返回的是HttpServletResponse成功返回excel文件流,失败就返回失败参数

下面是一个完整的 Spring Boot Controller 示例,根据业务逻辑判断返回 Excel 文件流或失败参数:

方案一:使用 HttpServletResponse 直接输出

import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/api/excel") public class ExcelExportController { @PostMapping("/export") public void exportExcel(@RequestBody ExportRequest request, HttpServletResponse response) { try { // 1. 业务逻辑判断是否成功 BusinessResult result = processBusiness(request); if (!result.isSuccess()) { // 2. 失败时返回 JSON 格式的错误信息 response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); Map<String, Object> errorResponse = new HashMap<>(); errorResponse.put("code", 500); errorResponse.put("message", result.getErrorMessage()); errorResponse.put("data", result.getErrorData()); // 设置 HTTP 状态码 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 写入错误信息 response.getWriter().write( new com.fasterxml.jackson.databind.ObjectMapper() .writeValueAsString(errorResponse) ); return; } // 3. 成功时返回 Excel 文件 byte[] excelData = generateExcel(result.getData()); // 设置响应头 String fileName = URLEncoder.encode("报表.xlsx", StandardCharsets.UTF_8.name()); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName); response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); // 写入 Excel 文件流 try (OutputStream os = response.getOutputStream()) { os.write(excelData); os.flush(); } } catch (Exception e) { // 异常处理 handleException(response, e); } } // 业务处理方法 private BusinessResult processBusiness(ExportRequest request) { // 模拟业务逻辑 if (request.getData() == null || request.getData().isEmpty()) { return BusinessResult.failure("导出数据不能为空", null); } // 其他业务逻辑... return BusinessResult.success("处理成功", request.getData()); } // 生成 Excel private byte[] generateExcel(List<Data> data) { // 使用 Apache POI 或其他库生成 Excel // 这里简化为示例 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); XSSFWorkbook workbook = new XSSFWorkbook()) { XSSFSheet sheet = workbook.createSheet("Sheet1"); // 填充数据... workbook.write(baos); return baos.toByteArray(); } catch (Exception e) { throw new RuntimeException("生成Excel失败", e); } } // 异常处理方法 private void handleException(HttpServletResponse response, Exception e) { try { response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); Map<String, Object> error = new HashMap<>(); error.put("code", 500); error.put("message", "服务器内部错误"); error.put("detail", e.getMessage()); response.getWriter().write( new com.fasterxml.jackson.databind.ObjectMapper() .writeValueAsString(error) ); } catch (Exception ex) { // 处理异常时的异常 } } }

方案二:使用 ResponseEntity 统一返回

import org.springframework.http.*; import org.springframework.web.bind.annotation.*; import org.springframework.core.io.ByteArrayResource; @RestController @RequestMapping("/api/excel") public class ExcelExportController2 { @PostMapping("/export2") public ResponseEntity<?> exportExcel(@RequestBody ExportRequest request) { try { BusinessResult result = processBusiness(request); if (!result.isSuccess()) { // 返回失败的 JSON 响应 Map<String, Object> errorResponse = new HashMap<>(); errorResponse.put("code", 400); errorResponse.put("message", result.getErrorMessage()); errorResponse.put("timestamp", System.currentTimeMillis()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .contentType(MediaType.APPLICATION_JSON) .body(errorResponse); } // 生成 Excel byte[] excelData = generateExcel(result.getData()); // 设置响应头 String fileName = "export_" + System.currentTimeMillis() + ".xlsx"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDisposition( ContentDisposition.attachment() .filename(fileName, StandardCharsets.UTF_8) .build() ); headers.setCacheControl("no-cache"); ByteArrayResource resource = new ByteArrayResource(excelData); return ResponseEntity.ok() .headers(headers) .contentLength(excelData.length) .body(resource); } catch (Exception e) { Map<String, Object> error = new HashMap<>(); error.put("code", 500); error.put("message", "导出失败"); error.put("detail", e.getMessage()); return ResponseEntity .status(HttpStatus.INTERNAL_SERVER_ERROR) .contentType(MediaType.APPLICATION_JSON) .body(error); } } }

辅助类定义

// 请求参数类 @Data public class ExportRequest { private String startDate; private String endDate; private List<Data> data; @Data public static class Data { private String name; private Integer value; } } // 业务结果类 @Data @AllArgsConstructor public class BusinessResult { private boolean success; private String errorMessage; private List<Data> data; public static BusinessResult success(String message, List<Data> data) { return new BusinessResult(true, message, data); } public static BusinessResult failure(String errorMessage, List<Data> data) { return new BusinessResult(false, errorMessage, data); } }

使用建议

  1. 方案一​ 更适合需要精细控制 HTTP 响应的场景

  2. 方案二​ 更符合 Spring 的编程风格,代码更简洁

  3. 文件命名:使用filename*=UTF-8''编码文件名,支持中文

  4. 响应头设置

    • 成功时设置application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

    • 失败时设置application/json

  5. 异常处理:确保异常时也能返回规范的错误信息

客户端调用示例

// 前端调用 fetch('/api/excel/export', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ startDate: '2024-01-01', endDate: '2024-12-31', data: [...] }) }) .then(async response => { const contentType = response.headers.get('content-type'); if (contentType.includes('application/json')) { // 错误响应 const error = await response.json(); console.error('导出失败:', error.message); } else if (contentType.includes('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')) { // Excel 文件 const blob = await response.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = '报表.xlsx'; a.click(); } });

这样设计可以确保:

  1. 成功时正确下载 Excel 文件

  2. 失败时返回结构化的错误信息

  3. 客户端可以根据 Content-Type 区分处理结果

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/27 21:55:56

对 CTF 兴趣满满?手把手教你从零基础到精通,这篇干货必须收藏

经常被问到类似的问题&#xff1a;CTF究竟该如何入门。其实这个问题问我并不合适&#xff0c;我也不是一个老赛棍&#xff0c;我和CTF的交集最多的大概是&#xff1a;很多CTF题目会直接或间接使用到我曾提到过的一些小技巧&#xff0c;我们称之为Tricks。 我觉得&#xff0c;入…

作者头像 李华
网站建设 2026/8/3 3:41:54

基于单片机的金属探测仪检测器报警系统设计

一、设计背景与核心需求 在公共安全检查&#xff08;如车站、机场&#xff09;、工业生产质检&#xff08;如食品加工、服装制造&#xff09;、考古勘探等场景中&#xff0c;金属异物的精准检测是保障安全与产品质量的关键。传统金属探测设备常存在检测灵敏度低、误报率高、功能…

作者头像 李华
网站建设 2026/7/31 4:30:59

【驱动量化交易17】教你如何通过股票数据api接口获取强势股池数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据

​ 如今&#xff0c;量化分析在股市领域风靡一时&#xff0c;其核心要素在于数据&#xff0c;获取股票数据&#xff0c;是踏上量化分析之路的第一步。你可以选择亲手编写爬虫来抓取&#xff0c;但更便捷的方式&#xff0c;莫过于利用专业的股票数据API接口。自编爬虫虽零成本&a…

作者头像 李华
网站建设 2026/7/31 8:52:03

使用TensorFlow进行商品图像检索系统开发

使用TensorFlow进行商品图像检索系统开发 在电商平台上&#xff0c;用户上传一张鞋子的照片&#xff0c;几秒钟后就能看到同款或相似款式的商品推荐&#xff1b;在智能仓库里&#xff0c;机器人通过摄像头识别货物外观&#xff0c;自动完成分拣入库——这些看似简单的操作背后…

作者头像 李华
网站建设 2026/7/28 16:09:12

MBA必备9个降AI率工具,高效避坑指南!

MBA必备9个降AI率工具&#xff0c;高效避坑指南&#xff01; AI降重工具&#xff1a;MBA论文的高效护航者 在当今学术写作中&#xff0c;随着人工智能技术的广泛应用&#xff0c;许多MBA学生在撰写论文时都面临一个共同挑战——如何有效降低AIGC率、去除AI痕迹&#xff0c;并确…

作者头像 李华
网站建设 2026/7/31 11:36:34

【Windows平台AI开发新纪元】:Open-AutoGLM本地化部署的7大核心技巧

第一章&#xff1a;Windows平台下Open-AutoGLM的环境准备与挑战在Windows平台上部署Open-AutoGLM面临多重技术挑战&#xff0c;包括依赖库冲突、Python版本兼容性以及CUDA驱动支持等问题。为确保模型顺利运行&#xff0c;必须构建一个稳定且隔离的开发环境。系统要求与基础依赖…

作者头像 李华