如何在Flutter移动应用中集成Jasper Report?
Flutter 连接并查看 Jasper Report 的实现方案
核心思路
Flutter客户端无法直接解析或渲染Jasper Report模板,需借助后端服务完成报表编译、数据填充与导出,再由Flutter调用接口获取成品报表(如PDF、HTML)并展示。
1. 后端实现(以Java Spring Boot为例)
通过后端生成报表文件并提供接口供Flutter调用:
import net.sf.jasperreports.engine.*; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController public class ReportController { // 模拟获取报表数据 private List<ReportData> getReportData(@RequestParam String userId) { // 实际场景可从数据库或其他API查询数据 return List.of(new ReportData("用户" + userId, "2024-05-20", 100.0)); } @GetMapping("/report/pdf") public ResponseEntity<byte[]> generatePdfReport(@RequestParam String userId) throws JRException { // 加载预编译的Jasper模板(.jasper文件) InputStream jasperStream = getClass().getResourceAsStream("/reports/UserReport.jasper"); JasperReport jasperReport = (JasperReport) JRLoader.loadObject(jasperStream); // 设置报表参数 Map<String, Object> parameters = new HashMap<>(); parameters.put("UserId", userId); parameters.put("ReportDate", "2024-05-20"); // 填充数据 JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(getReportData(userId)); JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource); // 导出为PDF字节流 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream); // 设置响应头,支持在线预览或下载 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_PDF); headers.setContentDispositionFormData("inline", "user_report.pdf"); return new ResponseEntity<>(outputStream.toByteArray(), headers, HttpStatus.OK); } } // 数据实体类 class ReportData { private String username; private String orderDate; private Double amount; public ReportData(String username, String orderDate, Double amount) { this.username = username; this.orderDate = orderDate; this.amount = amount; } // 省略getter方法 }
2. Flutter 端调用与展示
使用http请求后端接口,通过pdf_flutter展示PDF报表:
依赖配置
在pubspec.yaml中添加:
dependencies: http: ^1.2.1 pdf_flutter: ^1.2.1
代码实现
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:pdf_flutter/pdf_flutter.dart'; class JasperReportView extends StatefulWidget { final String userId; const JasperReportView({super.key, required this.userId}); @override State<JasperReportView> createState() => _JasperReportViewState(); } class _JasperReportViewState extends State<JasperReportView> { Uint8List? _pdfBytes; bool _isLoading = true; @override void initState() { super.initState(); _fetchReport(); } Future<void> _fetchReport() async { try { final response = await http.get( Uri.parse("http://你的后端IP:端口/report/pdf?userId=${widget.userId}"), ); if (response.statusCode == 200) { setState(() { _pdfBytes = response.bodyBytes; _isLoading = false; }); } } catch (e) { setState(() { _isLoading = false; }); // 处理请求错误,如弹窗提示 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("报表加载失败: $e")), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("用户报表")), body: _isLoading ? const Center(child: CircularProgressIndicator()) : _pdfBytes != null ? PDF.bytes( _pdfBytes!, fitPolicy: FitPolicy.BOTH, ) : const Center(child: Text("报表数据为空")), ); } }
3. 关键注意事项
- 开发阶段确保Flutter设备与后端服务处于同一局域网,使用后端本地IP而非
localhost - 生产环境需使用HTTPS接口,避免数据传输风险
- 若需要导出Excel/Word格式报表,可在后端更换Jasper的导出工具类(如
JasperExportManager.exportReportToXlsStream) - 复杂报表建议提前编译
.jrxml模板为.jasper文件,提升后端生成效率
内容的提问来源于stack exchange,提问作者shadid
相关产品推荐
相关产品推荐

