Показывать блоб (.pdf) в угловом приложении
Я пытался отобразить PDF-файл, который я получаю как блоб от $http.post
ответ. PDF должен отображаться в приложении с помощью <embed src>
например.
Я наткнулся на пару сообщений в стеке, но мой пример почему-то не работает.
JS:
Согласно этому документу, я продолжил и попробовал...
$http.post('/postUrlHere',{myParams}).success(function (response) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$scope.content = fileURL;
});
Теперь из того, что я понимаю, fileURL
создает временный URL, который блог может использовать в качестве ссылки.
HTML:
<embed src="{{content}}" width="200" height="200"></embed>
Я не уверен, как справиться с этим в Angular, идеальной ситуацией будет (1) присвоить его области, (2) "подготовить / перестроить" BLOB-объект в pdf (3) передать его в HTML, используя <embed>
потому что я хочу отобразить его в приложении.
Я занимаюсь исследованиями уже более суток, но почему-то не могу понять, как это работает в Angular... И давайте просто предположим, что библиотеки для просмотра PDF не были выбраны.
7 ответов
Прежде всего вам нужно установить responseType
в arraybuffer
, Это необходимо, если вы хотите создать блоб ваших данных. См. Отправка_ и получение_данных_данных. Итак, ваш код будет выглядеть так:
$http.post('/postUrlHere',{myParams}, {responseType:'arraybuffer'})
.success(function (response) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
});
Следующая часть - вам нужно использовать сервис $sce, чтобы angular доверял вашему URL. Это можно сделать следующим образом:
$scope.content = $sce.trustAsResourceUrl(fileURL);
Не забудьте ввести сервис $sce.
Если это все сделано, теперь вы можете вставить свой PDF:
<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>
Я использую AngularJS v1.3.4
HTML:
<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>
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();
});
};
});
JS услуги:
angular.module('xxxxxxxxApp')
.factory('xxxxServicePDF', function ($http) {
return {
downloadPdf: function () {
return $http.get('api/downloadPDF', { responseType: 'arraybuffer' }).then(function (response) {
return response;
});
}
};
});
Веб-службы 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;
}
Предложения Майкла работают для меня как обаяние:) Если вы замените $http.post на $http.get, помните, что метод.get принимает 2 параметра вместо 3... это то, где тратится впустую мое время...;)
контроллер:
$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);
});
Посмотреть:
<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>
Я столкнулся с трудностями при использовании "window.URL" с Opera Browser, так как это приведет к "undefined". Кроме того, с помощью window.URL документ PDF никогда не открывался в Internet Explorer и Microsoft Edge (он всегда будет ждать). Я предложил следующее решение, которое работает в IE, Edge, Firefox, Chrome и Opera (не тестировалось с Safari):
$http.post(postUrl, data, {responseType: 'arraybuffer'})
.success(success).error(failed);
function success(data) {
openPDF(data.data, "myPDFdoc.pdf");
};
function failed(error) {...};
function openPDF(resData, fileName) {
var ieEDGE = navigator.userAgent.match(/Edge/g);
var ie = navigator.userAgent.match(/.NET/g); // IE 11+
var oldIE = navigator.userAgent.match(/MSIE/g);
var blob = new window.Blob([resData], { type: 'application/pdf' });
if (ie || oldIE || ieEDGE) {
window.navigator.msSaveBlob(blob, fileName);
}
else {
var reader = new window.FileReader();
reader.onloadend = function () {
window.location.href = reader.result;
};
reader.readAsDataURL(blob);
}
}
Дайте мне знать, если это помогло!:)
Добавление responseType к запросу, сделанному из angular, действительно является решением, но для меня это не сработало, пока я не установил responseType в blob, а не в arrayBuffer. Код не требует пояснений:
$http({
method : 'GET',
url : 'api/paperAttachments/download/' + id,
responseType: "blob"
}).then(function successCallback(response) {
console.log(response);
var blob = new Blob([response.data]);
FileSaver.saveAs(blob, getFileNameFromHttpResponse(response));
}, function errorCallback(response) {
});
Самый последний ответ (для Angular 8+):
this.http.post("your-url",params,{responseType:'arraybuffer' as 'json'}).subscribe(
(res) => {
this.showpdf(res);
}
)};
public Content:SafeResourceUrl;
showpdf(response:ArrayBuffer) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
this.Content = this.sanitizer.bypassSecurityTrustResourceUrl(fileURL);
}
HTML :
<embed [src]="Content" style="width:200px;height:200px;" type="application/pdf" />
Последние пару дней я пытался загрузить PDF-файлы и изображения, все, что мне удалось загрузить, - это простые текстовые файлы.
Большинство вопросов имеют одинаковые компоненты, но потребовалось некоторое время, чтобы определить правильный порядок, чтобы он работал.
Спасибо @ Николай Мельников, ваш комментарий / ответ на этот вопрос заставил его работать.
В двух словах, вот мой внутренний вызов AngularJS Service:
getDownloadUrl(fileID){
//
//Get the download url of the file
let fullPath = this.paths.downloadServerURL + fileId;
//
// return the file as arraybuffer
return this.$http.get(fullPath, {
headers: {
'Authorization': 'Bearer ' + this.sessionService.getToken()
},
responseType: 'arraybuffer'
});
}
С моего контроллера:
downloadFile(){
myService.getDownloadUrl(idOfTheFile).then( (response) => {
//Create a new blob object
let myBlobObject=new Blob([response.data],{ type:'application/pdf'});
//Ideally the mime type can change based on the file extension
//let myBlobObject=new Blob([response.data],{ type: mimeType});
var url = window.URL || window.webkitURL
var fileURL = url.createObjectURL(myBlobObject);
var downloadLink = angular.element('<a></a>');
downloadLink.attr('href',fileURL);
downloadLink.attr('download',this.myFilesObj[documentId].name);
downloadLink.attr('target','_self');
downloadLink[0].click();//call click function
url.revokeObjectURL(fileURL);//revoke the object from URL
});
}
Предложение кода, который я только что использовал в своем проекте, использующем AngularJS v1.7.2
$http.get('LabelsPDF?ids=' + ids, { responseType: 'arraybuffer' })
.then(function (response) {
var file = new Blob([response.data], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$scope.ContentPDF = $sce.trustAsResourceUrl(fileURL);
});
<embed ng-src="{{ContentPDF}}" type="application/pdf" class="col-xs-12" style="height:100px; text-align:center;" />