杰瑞科技汇

Java POI如何实现Excel文件下载?

Java POI Excel 下载指南

Apache POI 是一个强大的 Java 库,用于处理 Microsoft Office 格式文件,包括 Excel,下面我将介绍如何使用 POI 来生成并下载 Excel 文件。

基本步骤

  1. 添加 POI 依赖
  2. 创建 Excel 工作簿和工作表
  3. 填充数据
  4. 设置响应头
  5. 输出 Excel 文件到客户端

完整代码示例

添加 Maven 依赖

<dependencies>
    <!-- POI 核心依赖 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    <!-- POI OOXML 支持 (用于 .xlsx 格式) -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
</dependencies>

控制器代码示例 (Spring Boot)

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
@RestController
@RequestMapping("/excel")
public class ExcelDownloadController {
    @GetMapping("/download")
    public ResponseEntity<byte[]> downloadExcel() throws IOException {
        // 1. 创建工作簿
        Workbook workbook = new XSSFWorkbook(); // 使用 .xlsx 格式
        // 2. 创建工作表
        Sheet sheet = workbook.createSheet("员工数据");
        // 3. 创建标题行
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("ID");
        headerRow.createCell(1).setCellValue("姓名");
        headerRow.createCell(2).setCellValue("年龄");
        headerRow.createCell(3).setCellValue("部门");
        // 4. 填充数据 (这里用模拟数据)
        List<Employee> employees = getMockEmployees();
        int rowNum = 1;
        for (Employee employee : employees) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(employee.getId());
            row.createCell(1).setCellValue(employee.getName());
            row.createCell(2).setCellValue(employee.getAge());
            row.createCell(3).setCellValue(employee.getDepartment());
        }
        // 5. 自动调整列宽
        for (int i = 0; i < 4; i++) {
            sheet.autoSizeColumn(i);
        }
        // 6. 写入到输出流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);
        workbook.close();
        // 7. 设置响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", "员工数据.xlsx");
        headers.setContentLength(outputStream.toByteArray().length);
        return ResponseEntity.ok()
                .headers(headers)
                .body(outputStream.toByteArray());
    }
    // 模拟数据方法
    private List<Employee> getMockEmployees() {
        // 实际项目中可以从数据库或其他数据源获取
        return List.of(
            new Employee(1, "张三", 28, "技术部"),
            new Employee(2, "李四", 32, "市场部"),
            new Employee(3, "王五", 25, "人事部")
        );
    }
    // 员工实体类
    static class Employee {
        private int id;
        private String name;
        private int age;
        private String department;
        // 构造方法、getter 和 setter
        public Employee(int id, String name, int age, String department) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.department = department;
        }
        // 省略 getter 和 setter...
    }
}

关键点说明

  1. 工作簿类型选择:

    • HSSFWorkbook: 用于 .xls 格式 (Excel 2003 及以前)
    • XSSFWorkbook: 用于 .xlsx 格式 (Excel 2007 及以后)
  2. 响应头设置:

    • Content-Type: 设置为 application/octet-stream 表示二进制流
    • Content-Disposition: 设置为 attachment 表示下载,并指定文件名
  3. 性能考虑:

    • 对于大数据量,考虑使用 SXSSF (流式 API) 来避免内存问题
    • 及时关闭工作簿和流资源

使用 SXSSF 处理大数据量

// 使用 SXSSF 处理大数据量
Workbook workbook = new SXSSFWorkbook(100); // 在内存中保留100行,其余写入临时文件
// 其他操作与 XSSFWorkbook 相同
// 最后清理临时文件
((SXSSFWorkbook) workbook).dispose();

前端调用示例

使用 JavaScript (Axios) 调用下载接口:

axios.get('/excel/download', {
    responseType: 'blob'
}).then(response => {
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', '员工数据.xlsx');
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
});

注意事项

  1. 确保在服务器端正确处理异常和资源释放
  2. 对于大型 Excel 文件,考虑使用异步处理或任务队列
  3. 根据需求设置适当的响应头,如缓存控制
  4. 考虑添加进度反馈机制,特别是对于大文件

希望这个指南对你有所帮助!如果有任何具体问题或需要更详细的示例,请随时提问。

分享:
扫描分享到社交APP
上一篇
下一篇