从 Spring @RestController 收到的 AngularJS 显示 PDF (byte[])
Posted
技术标签:
【中文标题】从 Spring @RestController 收到的 AngularJS 显示 PDF (byte[])【英文标题】:AngularJS Display PDF (byte[]) received from Spring @RestController 【发布时间】:2014-12-22 22:01:54 【问题描述】:我的要求是在表单提交/发布时在我的 Angular js 应用程序中显示(新标签)/下载/嵌入 PDF。
我不希望服务器返回生成的 PDF 的唯一标识符,而是使用 $window 服务打开一个新窗口,其 url 指向服务器端端点,该端点根据唯一标识符返回 PDf。因为我需要动态生成pdf(不存储在文件系统中)。
与AngularJS: Display blob (.pdf) in an angular app 类似的问题,但这对我不起作用。
我的控制器
angular.module('EvaluationResultsModule').controller('CA_EvaluationResultsCtrl',
[ '$scope', 'EvaluationResultsService', '$sce', function($scope, EvaluationResultsService, $sce)
$scope.showPDF = function()
$scope.result = CA_EvaluationResultsService.getEvalutaionResultPDF($scope.evaluationResults);
$scope.result.$promise.then(function(data)
var file = new Blob([data],
type : 'application/pdf'
);
var fileURL = URL.createObjectURL(file);
$scope.pdfContent = $sce.trustAsResourceUrl(fileURL);
);
]);
我的服务
angular.module('EvaluationResultsModule').factory('EvaluationResultsService', function($resource)
return $resource('./api/ca/evaluationResults/:dest', ,
getEvalutaionResultPDF :
method : 'GET',
params :
dest : "getPDF"
,
responseType : 'arraybuffer',
);
);
休息控制器方法
@RequestMapping(value = "/getPDF", method = RequestMethod.GET)
public byte[] getEvalutaionResultPDF()
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Generate PDF using Jasper
Map<String, Object> model = new HashMap<String, Object>();
List<User> usersList = null; //populated from Service layer;
JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(usersList);
JasperPrint jasperPrint = jasperPrint = JasperFillManager.fillReport(this.getClass().getClassLoader().getResourceAsStream("A4.jasper"), model, beanColDataSource);
JasperExportManager.exportReportToPdfStream(jasperPrint, baos);
return baos.toByteArray();
我的回复已登录控制台
response: Object data: ArrayBuffer, status: 200, headers: function, config: Object, statusText: "OK"config: Objectdata: ArrayBufferbyteLength: (...)__proto__: ArrayBufferbyteLength: [Exception: TypeError: Method ArrayBuffer.prototype.byteLength called on incompatible receiver #<ArrayBuffer>]get byteLength: function byteLength() [native code] constructor: function ArrayBuffer() [native code] slice: function slice() [native code] __proto__: Objectheaders: function (name) resource: Resourcestatus: 200statusText: "OK"__proto__: Object
【问题讨论】:
【参考方案1】:我使用此代码,它对我有用:
REST 控制器:
@RequestMapping(value = "/api/reports/pdf", method = RequestMethod.GET)
@Timed
public @ResponseBody byte[] getOpenedEventsInPdf(HttpServletResponse response)
response.setHeader("Content-Disposition", "inline; filename=file.pdf");
response.setContentType("application/pdf");
// get file in bytearray from my custom service in backend
byte[] file = jasperReportsService.getOpenedEventsReport(ReportFormat.PDF);
return file;
JS/Angular 控制器;
$scope.getPdf = function()
$http.get('/api/reports/pdf', responseType: 'arraybuffer')
.success(function (data)
var file = new Blob([data], type: 'application/pdf');
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
);
html 片段:
<a ng-click="getPdf()">Show PDF</a>
【讨论】:
感谢您简洁地回答一些需要一些时间才能找到的问题。 非常感谢......它对我有一点点改变...... +1。 如何处理Rest Controller中的异常? @Guus - 你可以从var contentDisposition = response.headers("Content-Disposition");
var filename = (contentDisposition.split(';')[1].trim().split('=')[1]).replace(/"/g, '');
的回复中得到它
@amallard 谢谢,我还找到了另一种方法。使用angular-file-saver
我现在可以做到FileSaver.saveAs(file, 'my_file_name.pdf');
【参考方案2】:
在下面的链接中,你应该可以找到答案:
AngularJS Display PDF (byte[]) received from Spring(@RestController) + jasper report
在此链接中,您可以了解如何使用 angularjs 在 iframe 中显示 pdf。 pdf 是使用 spring 和 jasper 报告从 API rest 接收的。
【讨论】:
您好,欢迎来到 SO。请编辑您的问题,使其至少包含可在该链接中找到的内容的摘要。如果链接失效,只包含一个链接的答案,没有任何解释或评论,可能会变得毫无用处。谢谢!【参考方案3】:对于“浏览器兼容性”,给定的代码工作正常:
从后端控制器端获取字节数组数据并生成 js 控制器端的文件 :
后端控制器
@RequestMapping(value = "/getPDF", method = RequestMethod.GET)
public byte[] getEvalutaionResultPDF()
byte[] data = //get byte Array from back-end service
return data;
JS 服务
var getPdfFile = function()
return $http.get("getPDF", responseType: 'arraybuffer');
;
JS 控制器
$scope.pdfFile = function()
service.getPdfFile().then(function (data)
//for browser compatibility
var ieEDGE = navigator.userAgent.match(/Edge/g);
var ie = navigator.userAgent.match(/.NET/g); // IE 11+
var oldIE = navigator.userAgent.match(/MSIE/g);
var name = "file";
var blob = new window.Blob([data.data], type: 'application/pdf' );
if (ie || oldIE || ieEDGE)
var fileName = name+'.pdf';
window.navigator.msSaveBlob(blob, fileName);
else
var file = new Blob([ data.data ],
type : 'application/pdf'
);
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = name+'.pdf';
document.body.appendChild(a);
a.click();
,
function(error)
//error
);
;
【讨论】:
以上是关于从 Spring @RestController 收到的 AngularJS 显示 PDF (byte[])的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Validated Spring RestController 获取多个缺失请求参数的详细信息?
Angular 从 Spring RestController 获取图像并缓存它
Spring @RestController,spring-boot 出现意外错误(类型=不可接受,状态=406)
Spring @RestController 生成没有命名空间的 XML