如何将ModelAndView对象转换为byte[]数组,提取Excel作为邮件附件
解决方案
你自定义的ExcelGenerator本质是Spring的View接口实现类,Excel生成逻辑全部封装在视图渲染方法中,ModelAndView仅存储视图实例和数据模型,本身不持有渲染后的文件字节流,所以不需要从ModelAndView中提取数据,直接复用ExcelGenerator的生成逻辑即可拿到字节数组,有两种可选实现方案:
方案1:直接模拟视图渲染流程生成字节数组(无需修改原有代码,快速实现)
借助Spring测试包的Mock响应对象模拟Web请求的渲染流程,直接拿到输出的字节数组:
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; // 构造和原有接口完全一致的Model参数 Map<String, Object> model = new HashMap<>(); Map<String, List> multipleList = new HashMap<>(); multipleList.put("test1 sheet", DataGenerator.generatePopulatedObjects(ExportClassExample.class, 10)); multipleList.put("test2 sheet", DataGenerator.generatePopulatedObjects(IdExportClassExample.class, 10)); multipleList.put("test3 sheet", DataGenerator.generatePopulatedObjects(ExportClassExample.class, 100)); model.put(ExcelGenerator.MULTIPLE_DATA_LIST, multipleList); // 模拟渲染流程获取字节数组 MockHttpServletRequest mockRequest = new MockHttpServletRequest(); MockHttpServletResponse mockResponse = new MockHttpServletResponse(); new ExcelGenerator().render(model, mockRequest, mockResponse); byte[] excelBytes = mockResponse.getContentAsByteArray();
拿到excelBytes后即可直接构造邮件附件,示例如下:
import javax.mail.util.ByteArrayDataSource; import javax.mail.internet.MimeBodyPart; // 构造附件 ByteArrayDataSource dataSource = new ByteArrayDataSource(excelBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); MimeBodyPart attachmentPart = new MimeBodyPart(); attachmentPart.setDataHandler(new DataHandler(dataSource)); attachmentPart.setFileName("多列表数据导出.xlsx");
如果不想引入spring-test依赖,可直接使用ByteArrayOutputStream对接ExcelGenerator的写入逻辑,参考方案2。
方案2:抽取公共生成方法(解耦性更强,推荐长期使用)
将ExcelGenerator中Excel生成的核心逻辑抽取为独立公共方法,同时兼容Web请求响应和字节数组生成场景:
- 修改
ExcelGenerator代码:
public class ExcelGenerator extends AbstractView { public static final String MULTIPLE_DATA_LIST = "multipleDataList"; // 抽取公共Excel生成方法,接收数据模型和输出流 public void generateExcel(Map<String, Object> model, OutputStream outputStream) throws IOException { // 将原有render方法中生成Excel、写入输出流的核心逻辑迁移到此处 } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 原有响应头设置逻辑保留 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment;filename=export.xlsx"); // 调用公共方法生成Excel generateExcel(model, response.getOutputStream()); } }
- 生成字节数组直接调用公共方法即可:
ByteArrayOutputStream out = new ByteArrayOutputStream(); new ExcelGenerator().generateExcel(model, out); byte[] excelBytes = out.toByteArray();
内容的提问来源于stack exchange,提问作者Marius Pop
相关产品推荐
相关产品推荐

