Failed to load PDF document - Angular JS - BLOB - angularjs

I am trying to get PDF document from Web API, and want to show in Angular App. Getting "Failed to load PDF document error".
I have followed
"AngularJS: Display blob (.pdf) in an angular app" post.
Whereas, i can download the same file successfully by following "Download file from an ASP.NET Web API method using AngularJS" post.
Looks like i am getting the file as "Chunked Transfer Encoded". Somehow this is not getting decoded when trying to show in angular app. Please advise.
Web API Code:
HttpResponseMessage result = null;
var localFilePath = #"C:\Test.pdf";
if (!File.Exists(localFilePath))
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{// serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition.FileName = "Test.pdf";
result.Content.Headers.Add("x-filename", "Test.pdf");
}
return result;
Angular Controller:
myModule.controller("pdfviewerController", function ($scope, $http, $log, $sce) {
$http.post('/api/Sample/GetTestFile', {responseType:'arraybuffer'})
.success(function (response) {
var file = new Blob([response], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$scope.content = $sce.trustAsResourceUrl(fileURL);
});
});
HTML Template:
<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>

problem is there in controller.
{responseType:'arraybuffer'} is verymuch required.
For $http.get - It should be second parameter.
For $http.post - It should be third parameter.
In above case, i am using $http.post and i have passed {responseType:'arraybuffer'} as second parameter.
$http.post('/api/Sample/GetTestFile', {responseType:'arraybuffer'})
Corrected code
$http.post('/api/Sample/GetTestFile','', {responseType:'arraybuffer'})

Related

How to get PDF downloaded in $resource put service angularjs1

I want to download a PDF from server depending on the input request sent from UI . I am getting a pop-up with [object objcet] written on it .
Can somebody help me out in this .
P.S. : I have to use $resource only , not the $http one , thanks :)
This is my Service call to WEB API , Service name is "GetInvoice"-->
function ($resource) {
return $resource('app/rest/invoice/:id', null, {
'update': { method:'PUT'}
},{ headers: {'Content-Type': 'application/pdf'},
transformRequest: []});
}
This is my service call from controller -->
GetInvoice.update({id:'1'},angular.toJson(invoiceJSON)).$promise.then(function (data) {
var file = new Blob([data]);
var fileURL = ($window.URL || $window.webkitURL).createObjectURL(file);
$window.open(fileURL, '_blank', 'download');});
Change the line
var file = new Blob([data]);
to
var file = new Blob([data.data]);
and check out.
If this doesn't work out,
dynamically create a anchor tag and invoke the click event which will open a popup / new tab with the content. Refer here

AngularJS Spring MVC Redirection with data binding

I am new to AngularJS and the question may not be very smart.
I am trying to redirect to a new page with data-binding from Spring Controller.
My requirement is that when I click on a button/hyperlink on a page (say page 1), my Spring Controller performs business and determines which page to display (either page 2 or page 3). The data in the redirected page is populated from Spring Controller during redirection using query params.
My problem is that the page redirects just fine. But I am unable to retrieve the query params in AngularJS, though I can view them in the redirection request URL in browser (Google developer tools).
I have only added the relevant code :
Controller method called from first jsp page (say page1.jsp) to redirect to page2 (pageToRedirectTo.jsp)
In page1.jsp, there is a button that calls the method for page redirection along with form object.
<button ng-click="ctrl.onClickOfPage1ButtonRedirect ()">Page Redirect</button>
app.js
var angularApp = angular.module('angularApp',[]);
AngularJs Controller
this.onClickOfPage1ButtonRedirect = function(){
Page1Service.redirectToNewPage()
.then(
function(d) {
$scope.myVal = d;
var e1 = angular.element(document.getElementById("dir"));
e1.html(d);
$compile(e1.contents())($scope);
},
function(errResponse){
console.error('Error.');
}
);
};
AngularJS Service that sends request to Spring Controller
Page1Service.js
angularApp.factory('Page1Service', ['$http', '$q', function($http, $q){
return {
redirectToNewPage: function() {
return $http.post('/requestMappingUrlFromPage1')
.then(
function(response){
return response.data;
},
function(errResponse){
return $q.reject(errResponse);
}
);
}
};
}]);
Spring Controller
#RequestMapping(value="/requestMappingUrlFromPage1", method = RequestMethod.POST)
public ResponseEntity<Void> redirectToNewPage(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
List<ResponseDTO> responseDTO = new ArrayList<ResponseDTO>();
//Business logic to populate responseDTO list ....
String responseJson= new Gson().toJson(responseDTO);
UriComponentsBuilder b = UriComponentsBuilder.fromPath("/pageToRedirectTo");
UriComponents uriComponents = b.queryParam("responseDTOList", responseJson).build();
return new ResponseEntity<Void>(headers,HttpStatus.FOUND);
}
Now, when I get the response in Page1Service.js, it displays the response.data as the html content of the page being redirected to. In Google Chrome developer tools, I can see the query parameters :
responseDTOList:[{"parameter1":"123","parameter2":"Name","parameter3":false,"parameter4":false},{"parameter1":"123123","parameter2":"Name1","parameter3":false,"parameter4":false}]
Response received in Page1Service.js
Object {data: "<!DOCTYPE html>
↵<html ng-app="angularApp">
↵<head>
.......
↵</body>
↵
↵</html>", status: 200, config: Object, statusText: "OK"}
Is there a way to retrieve this data?
I have tried using $route.params, but it is undefined. Also, I am not using ng-route. Using $location is also not useful as all my pages are dynamically embedded in the custom dir tag in home page, so $location.absUrl() always gives the home page url.
Any suggestions are much appreciated. Thanks a lot in advance!!
I have added the browser header params that shows the response object in my Query Params. Angular response.data, however, displays just the HTML content, and I am unable to retrieve the query params.
Link to view the Browser headers : browser headers
The idea which pop in my head after examine your problem is that the one way of achieving your target is to convert angularJS page into Thymeleaf page. Its very simple to convert it and your all angularJS code will remain same. Please see Thymeleaf doc for this purpose.
Then simply you can get params in js script like this
<script th:inline="javascript">
/*<![CDATA[*/
var message = [[${message}]];
console.log(message);
/*]]>*/
</script>
Once you got your parms in Javascript then you can easily get into angularJS Controller.
If you are getting Page1Service.js response.data as HTML you can use JSON.parse to parse the content and get data.
it will be helpful to provide ans if you make it more clear "when I get the response in Page1Service.js, it displays the response.data as the html content of the page being redirected to."
I am not sure of it is possible to retrieve response data from query parameters in AngularJS.
However, I solved my problem by retrieving the query params in the GET request of the redirected page in Spring Controller. Then, I am sending it back to Angular Service via the HttpServletResponse header and retrieving it back in AngularJS.
Probably not the ideal solution, but that's the fix I could find in a short period without major restructuring of my code.
Spring Controller for redirection from page1 to page2
#RequestMapping(value="/requestMappingUrlFromPage1", method = RequestMethod.POST)
public ResponseEntity<Void> redirectToNewPage(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
List<ResponseDTO> responseDTO = new ArrayList<ResponseDTO>();
//Business logic to populate responseDTO list ....
String responseJson= new Gson().toJson(responseDTO);
UriComponentsBuilder b = UriComponentsBuilder.fromPath("/pageToRedirectTo");
UriComponents uriComponents = b.queryParam("responseDTOList", responseJson).build();
return new ResponseEntity<Void>(headers,HttpStatus.FOUND);
}
Redirected Page Controller mapping
#RequestMapping(value="/pageToRedirectTo",method = RequestMethod.GET)
public String getpageToRedirectTo(#RequestParam(required=false, name="responseDTOList")String temp, HttpServletRequest request,HttpServletResponse response) {
try{
if(temp!=null){
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//JSON from String to Object
List<ResponseDTO> objList = mapper.readValue(temp,TypeFactory.defaultInstance().constructCollectionType(List.class,ResponseDTO.class));
if(objList!=null){
String jsonList = new Gson().toJson(objList);
response.setHeader("responseDTOList", jsonList);
}
}
}catch(JsonMappingException jme){
logger.error("JsonMappingException : ", jme);
}catch(JsonParseException jpe){
logger.error("JsonParseException : ", jpe);
}
catch(IOException ioe){
logger.error("IOException : ", ioe);
}catch(Exception e){
logger.error("Error : ", e);
}
return "pageToRedirectTo";
}
Page1Service.js
angularApp.factory('Page1Service', ['$http', '$q', function($http, $q){
return {
redirectToNewPage: function() {
return $http.post('/requestMappingUrlFromPage1')
.then(
function(response){
var customResponse = {};
customResponse.responseDTOList= response.headers('responseDTOList');
customResponse.pageData = response.data;
return customResponse;
},
function(errResponse){
return $q.reject(errResponse);
}
);
}};}]);
AngularJS Controller
this.onClickOfPage1ButtonRedirect = function(){
Page1Service.redirectToNewPage()
.then(
function(d) {
$scope.responseList = d.responseDTOList;
$scope.myVal = d.pageData;
var e1 = angular.element(document.getElementById("dir"));
e1.html(d);
$compile(e1.contents())($scope);
},
function(errResponse){
console.error('Error.');
}
);
};

Open a PDF in a new window of the browser with angularjs

I'm new to angular js and I wish to open a PDF document in a new window of the browser after pressing a button.
I make a GET request with $http.get() at front end, at backend there is a Java rest service that respond to the GET and generates a PDF. I wish to open this PDF on the browser.
If is not possible to open the PDF in this way then at least open any PDF with AngularJs, how could I do this?
#GET
#Path("/printPdf")
public Response printService(){
//generates the pdf
File reportFile = new File(filePath);
String name = reportName + "." + "pdf";
ResponseBuilder response = Response.ok(new TemporaryFileInputStream(reportFile));
response.header("Content-Disposition", "attachment; filename=" + name);
response.header("Content-Type", "application/pdf");
response.header("Access-Control-Expose-Headers", "x-filename");
response.header("x-filename", name);
return response.build();
}
this is what there is at backend to generate the response in the rest service.
If you had something like this:
var myPdfUrl = 'something'
$http.get(myPdfUrl);
Do this instead:
var myPdfUrl = 'something'
$window.open(myPdfUrl);
If instead you have something like this:
$http
.get(generatePdfUrl)
.then(function(data){
//data is link to pdf
});
Do this:
$http
.get(generatePdfUrl)
.then(function(data){
//data is link to pdf
$window.open(data);
});
Maybe this can help,in the case of you have something like this :
$http.get('generatePdfUrl')
.then(function (data) { // data is your url
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
});
Then use your service in controller and do
$window.open(fileURL);

AngularJS Web Api HttpHandler Image Downloader

My AngularJS application is interacting with ASP.NET Web API to full fill the request which is working fine. it has an use case that allows user to download user specific secure PDF document. I have implemented this functionality as below
AngularJS:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
$scope.DownloadHandler = function (id, downloadURL) {
FileStreamManager.getPdf(id, downloadURL)
.then(function (result) {
// success
window.open(downloadURL + id, '_self', '');
},
function (result) {
$scope.errors = result.data;
});
};
Note : downloadURL is the Controller call like \ImageRepo\Get
Web Api Controller I have this implementation:
HttpResponseMessage response = new HttpResponseMessage();
// DB call to to build the URL
string fileName = "myLocation\Image\doc.pdf";
if (!fileProvider.Exists(fileName))
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
FileStream fileStream = fileProvider.Open(fileName);
response.Content = new StreamContent(fileStream);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentLength = fileProvider.GetLength(fileName);
return response;
Which is working fine. Due to the security issue, i was asked to implement this by using HttpHanlder which is pretty new to me. I have some question on the same.
Should my AngularJS ng-click calls to my .ashx handler directly instead of a Controller URL? Or Should this call route through Controller? How?
I have DB calls to build the image URL and update some the status. Can this be done in Handler itself?
How would i make sure my documents are secured while downloading?
Please help.

Outputting a PDF (created with FPDF) in AngularJS

I am using FPDF to create a PDF on a Laravel backend that serves Angular. I have created it in the normal FPDF way and I am unsure how to send the file response back to Angular.
I read here about generall how to go about it by configuring my $http request as below:
return $http({url: '/api/print/class-list', method: "POST", data: {data: data}, headers: {'Accept':'application/pdf'}, responseType: 'arrayBuffer'})
.then(function(response)
{
console.log(response.data);
var file = new Blob([response.data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
var content = $sce.trustAsResourceUrl(fileURL);
return content;
}
I have injected $sce in the service and i am outputting the content in an embed tag. The tag just shows an empty PDF. I am wondering what the problem could be. Also, on the Laravel side, once I am done creating the PDF by writing $pdf->Output("page","D"), is there a way i should write return something so that it can be returned to Angular?
Also, when i console response, it kindof returns blob or some pdf stuff, and a number of errors after that like:
"Warning: Unsupported feature "unknown"

Resources