Cómo mostrar blob (.pdf) en una aplicación AngularJS
He estado intentando mostrar un archivo pdf que obtengo como un blob de una $http.post
respuesta. El pdf debe mostrarse dentro de la aplicación usando, <embed src>
por ejemplo.
Me encontré con un par de publicaciones de pila pero de alguna manera mi ejemplo no parece funcionar.
JS:
Según este documento , seguí y probé...
$http.post('/postUrlHere',{myParams}).success(function (response) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$scope.content = fileURL;
});
Ahora, según tengo entendido, fileURL
crea una URL temporal que el blog puede usar como referencia.
HTML:
<embed src="{{content}}" width="200" height="200"></embed>
No estoy seguro de cómo manejar esto en Angular, la situación ideal sería (1) asignarlo a un alcance, (2) 'preparar/reconstruir' el blob en un pdf (3) pasarlo al HTML usando <embed>
porque desea mostrarlo dentro de la aplicación.
He estado investigando durante más de un día, pero de alguna manera parece que no puedo entender cómo funciona esto en Angular... Y supongamos que las bibliotecas del visor de PDF disponibles no eran una opción.
En primer lugar, debe configurar el responseType
archivo en arraybuffer
. Esto es necesario si desea crear un blob de sus datos. Consulte Envío_y_recepción_datos_binarios . Entonces tu código se verá así:
$http.post('/postUrlHere',{myParams}, {responseType:'arraybuffer'})
.success(function (response) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
});
La siguiente parte es que necesitas usar el servicio $sce para hacer que angular confíe en tu URL. Esto se puede hacer de esta manera:
$scope.content = $sce.trustAsResourceUrl(fileURL);
No olvides inyectar el servicio $sce .
Si todo esto está hecho, ahora puede incrustar su pdf:
<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>
Yo uso AngularJS v1.3.4
HTML:
<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>
Controlador JS:
'use strict';
angular.module('xxxxxxxxApp')
.controller('xxxxController', function ($scope, xxxxServicePDF) {
$scope.downloadPdf = function () {
var fileName = "test.pdf";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
xxxxServicePDF.downloadPdf().then(function (result) {
var file = new Blob([result.data], {type: 'application/pdf'});
var fileURL = window.URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
});
};
});
Servicios JS:
angular.module('xxxxxxxxApp')
.factory('xxxxServicePDF', function ($http) {
return {
downloadPdf: function () {
return $http.get('api/downloadPDF', { responseType: 'arraybuffer' }).then(function (response) {
return response;
});
}
};
});
Servicios web Java REST - Spring MVC:
@RequestMapping(value = "/downloadPDF", method = RequestMethod.GET, produces = "application/pdf")
public ResponseEntity<byte[]> getPDF() {
FileInputStream fileStream;
try {
fileStream = new FileInputStream(new File("C:\\xxxxx\\xxxxxx\\test.pdf"));
byte[] contents = IOUtils.toByteArray(fileStream);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "test.pdf";
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
return response;
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
return null;
}
Las sugerencias de Michael funcionan de maravilla para mí :) Si reemplazas $http.post con $http.get, recuerda que el método .get acepta 2 parámetros en lugar de 3... aquí es donde pierdo el tiempo... ;)
controlador:
$http.get('/getdoc/' + $stateParams.id,
{responseType:'arraybuffer'})
.success(function (response) {
var file = new Blob([(response)], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$scope.content = $sce.trustAsResourceUrl(fileURL);
});
vista:
<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>