Trying to view data as pdf , pdf is blank - reactjs

I am trying to open a pdf file in the next tab, it opens but is always blank. I am calling a pdf file from a folder in my springboot. The data does show in the console log .
Spring code:
#RequestMapping(value = "/report", method = RequestMethod.GET)
void getFile(HttpServletResponse response) throws IOException {
String fileName = "test123.pdf";
String path = "TrainingDocuments/SuperPartnerUser/" + fileName;
File file = new File(path);
FileInputStream inputStream = new FileInputStream(file);
response.setContentType("application/pdf");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "inline;filename=\"" + fileName + "\"");
FileCopyUtils.copy(inputStream, response.getOutputStream());
}
React code:
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:application/pdf;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('target','_blank');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function test () {
Api(`tempFileDownload/report`, 'Get',"",3).then((data) => {
console.log(data);
download("test",data)
const file = new Blob([ data ], { type: 'application/pdf' });
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
window.open(fileURL);
});
}
Pdf data
Blank PDF

Issue was the api call for the frontend, backend works fine;
Reponse type needed to be blob
const result = await axios({
url: `${localUrl + url}`, //your url
method: 'GET',
responseType: 'blob', // important
})
.then(({ data }) => data);
return result;

Related

React Fetch download a pdf from Java REST API won't read in Adobe

I have tested the API in Postman and the PDF renders fine. So I know the API is working correctly.
When I fetch the PDF from within my React code Adobe gives me the error: "Adobe Acrobat cannot open the because it is neither a supported file type or because the file has been damaged"
My React code:
const downloadFile = async uploadId => {
const response = await callFetch("/uploads/download/" + uploadId + "?officerId=" + officerId, "GET", "");
if (response.status === 401 || response.status === 403) {
alert("Error " + response.status);
sessionStorage.clear();
return;
}
const file = response.blob();
const url = URL.createObjectURL(
new Blob([file], {type:"application/pdf"})
);
const link = document.createElement('a');
link.href = url;
link.setAttribute(
'download',
`FileName.pdf`,
);
// Append to html link element page
document.body.appendChild(link);
// Start download
link.click();
// Clean up and remove the link
link.parentNode.removeChild(link);
URL.revokeObjectURL(url);
};
const callFetch = (endpoint, method, jsonStr) => {
let myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Accept","application/json");
return callFetchApi(endpoint, method, jsonStr, myHeaders);
};
const callFetchApi = (endpoint, method, data, myHeaders) => {
const serverName = "http://localhost:8080/AuxPolice/api";
myHeaders.append("Access-Control-Allow-Credentials", 'true');
myHeaders.append("Access-Control-Allow-Origin", '*');
const jwt = sessionStorage.getItem("jwt");
let headerJwt = "Bearer " + jwt;
if (jwt != null) {
myHeaders.append("Authorization", headerJwt);
}
let myInit = {method: method
,headers: myHeaders
};
let url = serverName + endpoint;
if (data) {
myInit.body = data;
}
let returnFetch = fetch(url, myInit);
return returnFetch;
};
Here is my Java code:
#GetMapping(value = "/download" + "/{id}")
public ResponseEntity<Resource> downloadGet(#PathVariable Long id, #RequestParam Long officerId) throws SQLException
{
Officer loggedInOfficer = this.auxPoliceService.getOfficer(officerId);
Upload paramRec = new Upload();
paramRec.setUploadId(id);
Upload download = auxPoliceService.getUploads(loggedInOfficer.getOfficerId(), paramRec).get(0);
Blob blob = download.getBlob();
byte [] bytes = blob.getBytes(1, (int)blob.length());
blob.free();
InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(bytes));
String filename = download.getFilename();
String contentType = "application/pdf; name=\"" + filename() + "\"";
HttpHeaders headers = new HttpHeaders();
headers.set("content-disposition", "inline; filename=" + filename);
return ResponseEntity.ok()
.headers(headers)
.contentLength(bytes.length)
.contentType(MediaType.parseMediaType(contentType))
.body(resource);
}
Any ideas?

how to export data into CSV and PDF files using angularjs

I want to, when i click on button (separate for both CSV and PDF), it automatically download in CSV and PDF file with correct Formatting.
this CSV code i want to add PDF inside code
$scope.downloadData = function() {
var datasets = $scope.datasets.reverse();
var file_name = $scope.m_id+ '.csv';
var dataUrl = 'data:text/csv;charset=utf-8,';
var json = [];
if(datasets !== null) {
for(idx = 0; idx < datasets.length; idx++) {
var dataset = datasets[idx].data;
var time = datasets[idx].timestamp;
time = $filter('date')(time, "dd/MMMM/yyyy-hh:mm a");
dataset.time = time;
json.push(dataset);
}
var fields = Object.keys(json[0]);
var csv = json.map(
function(row) {
return fields.map(
function(fieldName) {
return '"' + (row[fieldName] || '') + '"';
}
);
}
);
csv.unshift(fields);
var csv_str = csv.join('%0A');
var downloadURL = dataUrl + csv_str;
var saveAs = function(uri, filename) {
var link = document.createElement('a');
if (typeof link.download === 'string') {
document.body.appendChild(link); // Firefox requires the link to be in the body
link.download = filename;
link.href = uri;
link.target = "_blank";
link.click();
document.body.removeChild(link); // remove the link when done
} else {
location.replace(uri);
}
};
saveAs(downloadURL, file_name);
} else {
$scope.err_msg = 'Failed to get data. Try reloading the page.';
}
};
I try some of script i found on internet, but it is not working, some have formatting issue and save have downloading.
In Advance Thanks.
You should use this awesome library for pdf/csv or whatever else formats.. File Saver
Here's is code example, service created using FileSaver
function download(api, file, contentType) {
var d = $q.defer();
$http({
method: 'GET',
url: api,
responseType: 'arraybuffer',
headers: {
'Content-type': contentType
}
}).success(function(response) {
var data = new Blob([response], {
type: contentType+ ';charset=utf-8'
});
FileSaver.saveAs(data, file);
d.resolve(response);
}).error(function(response) {
d.reject(response);
});
return d.promise;
}
file input is name of file, you can use same service and pass the types and file names direct from controller.
Let;s you service name is homeService
for pdf call
homeservice.download('/api/download/whaever', 'export.pdf', 'application/pdf')

Download the file using angular [duplicate]

download any file using ResponseEntity with angular does not work
I need to download a file using angular in client side,
this file can have any format it could be a pdf or excel or image or txt ...
my method works just for txt files and gives me a fail format for excel and image and for the pdf it gives an empty pdf.
so in my controller here is the function that calles the service method:
vm.downloadFile = downloadFile;
function downloadFile(file){
var urlDir = "C://STCI//"+idpeticion;
return VerDocServices.downloadFile(file,urlDir)
.then(function(response) {
var data = response.data;
var filename = file;
var contentType = 'application/octet-stream';//octet-stream
var linkElement = document.createElement('a');
try {
var blob = new Blob([ data ], {
type : contentType
});
var url = window.URL.createObjectURL(blob);
linkElement.setAttribute('href', url);
linkElement.setAttribute("download", filename);
var clickEvent = new MouseEvent("click", {
"view" : window,
"bubbles" : true,
"cancelable" : false
});
linkElement.dispatchEvent(clickEvent);
} catch (ex) {
console.log(ex);
throw ex;
}
}).catch(function(response) {
alert('Se ha producido un error al exportar del documento');
console.log(response.status);
throw response;
});
}
and my service.js has:
angular.module('mecenzApp').service('VerDocServices',['$http',function($http) {
this.downloadFile = function(file,urlDir) {
return $http.get('api/downloadFile', {
params : {
file : file,
urlDir : urlDir
}
}); }} ]);
And my service method is this:
#GetMapping("/downloadFile")
#Timed
public ResponseEntity<byte[]> downloadFile(#RequestParam(value = "file") String file, #RequestParam(value = "urlDir") String urlDir) {
log.debug("GET ---------------- DOWNLOAD FILE : {}", file);
log.debug("GET ---------------- From the DIRECTORY: {}",urlDir);
InputStream fileStream;
String filepath = urlDir+File.separator+file;
try {
File f = new File(filepath);
log.debug("GET ---------------- FILE: {}",f.getPath());
fileStream = new FileInputStream(f);
byte[] contents = IOUtils.toByteArray(fileStream);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/octet-stream"));
String filename = file;
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response2 = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
fileStream.close();
return response2;
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
return null;
}
could you plz take a look and tell me what did I have missed??
Thank youuu :)
How to Download Binary Files with AngularJS
When downloading binary files, it is important to set the responseType:
app.service('VerDocServices',['$http',function($http) {
this.downloadFile = function(url, file, urlDir) {
var config = {
//SET responseType
responseType: 'blob',
params : {
file : file,
urlDir : urlDir
}
};
return $http.get(url, config)
.then(function(response) {
return response.data;
}).catch(function(response) {
console.log("ERROR: ", response.status);
throw response;
});
};
}]);
If the responseType is omitted the XHR API defaults to converting UTF-8 encoded text to DOMString (UTF-16) which will corrupt PDF, image, and other binary files.
For more information, see MDN Web API Reference - XHR ResponseType
I don't know much about the backend, but I'll provide what i have used may be it will help, so On the Java Script File:
//your $http(request...)
.success(function (data, status, headers, config) {
//Recieves base64 String data
var fileName = 'My Awesome File Name'+'.'+'pdf';
//Parsing base64 String...
var binaryString = window.atob(data);
var binaryLen = binaryString.length;
var fileContent = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
fileContent[i] = ascii;
}
var blob = new Blob([fileContent], { type: 'application/octet-stream' }); //octet-stream
var fileURL = window.URL.createObjectURL(blob);
$sce.trustAsResourceUrl(fileURL); //allow angular to trust this url
//Creating the anchor download link
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it's not visible
angular.element(document.body).append(anchor); // Attach it to the document
anchor.attr({
href: fileURL,
target: '_blank',
download: fileName
})[0].click();
anchor.remove(); // Clean it up afterwards
})
//.error(function(...
And On your backend, make sure that your webservice produces octet-stream and returning the file in base64 data format, i did this using Java JAX-RS like this:
#POST
#Path("/downloadfile")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(...){
String base64String = Base64.getEncoder().encodeToString(/*here you pass your file in byte[] format*/);
return Response.ok(base64String).build();
}

Binary files corrupted - How to Download Binary Files with AngularJS

download any file using ResponseEntity with angular does not work
I need to download a file using angular in client side,
this file can have any format it could be a pdf or excel or image or txt ...
my method works just for txt files and gives me a fail format for excel and image and for the pdf it gives an empty pdf.
so in my controller here is the function that calles the service method:
vm.downloadFile = downloadFile;
function downloadFile(file){
var urlDir = "C://STCI//"+idpeticion;
return VerDocServices.downloadFile(file,urlDir)
.then(function(response) {
var data = response.data;
var filename = file;
var contentType = 'application/octet-stream';//octet-stream
var linkElement = document.createElement('a');
try {
var blob = new Blob([ data ], {
type : contentType
});
var url = window.URL.createObjectURL(blob);
linkElement.setAttribute('href', url);
linkElement.setAttribute("download", filename);
var clickEvent = new MouseEvent("click", {
"view" : window,
"bubbles" : true,
"cancelable" : false
});
linkElement.dispatchEvent(clickEvent);
} catch (ex) {
console.log(ex);
throw ex;
}
}).catch(function(response) {
alert('Se ha producido un error al exportar del documento');
console.log(response.status);
throw response;
});
}
and my service.js has:
angular.module('mecenzApp').service('VerDocServices',['$http',function($http) {
this.downloadFile = function(file,urlDir) {
return $http.get('api/downloadFile', {
params : {
file : file,
urlDir : urlDir
}
}); }} ]);
And my service method is this:
#GetMapping("/downloadFile")
#Timed
public ResponseEntity<byte[]> downloadFile(#RequestParam(value = "file") String file, #RequestParam(value = "urlDir") String urlDir) {
log.debug("GET ---------------- DOWNLOAD FILE : {}", file);
log.debug("GET ---------------- From the DIRECTORY: {}",urlDir);
InputStream fileStream;
String filepath = urlDir+File.separator+file;
try {
File f = new File(filepath);
log.debug("GET ---------------- FILE: {}",f.getPath());
fileStream = new FileInputStream(f);
byte[] contents = IOUtils.toByteArray(fileStream);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/octet-stream"));
String filename = file;
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response2 = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
fileStream.close();
return response2;
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
return null;
}
could you plz take a look and tell me what did I have missed??
Thank youuu :)
How to Download Binary Files with AngularJS
When downloading binary files, it is important to set the responseType:
app.service('VerDocServices',['$http',function($http) {
this.downloadFile = function(url, file, urlDir) {
var config = {
//SET responseType
responseType: 'blob',
params : {
file : file,
urlDir : urlDir
}
};
return $http.get(url, config)
.then(function(response) {
return response.data;
}).catch(function(response) {
console.log("ERROR: ", response.status);
throw response;
});
};
}]);
If the responseType is omitted the XHR API defaults to converting UTF-8 encoded text to DOMString (UTF-16) which will corrupt PDF, image, and other binary files.
For more information, see MDN Web API Reference - XHR ResponseType
I don't know much about the backend, but I'll provide what i have used may be it will help, so On the Java Script File:
//your $http(request...)
.success(function (data, status, headers, config) {
//Recieves base64 String data
var fileName = 'My Awesome File Name'+'.'+'pdf';
//Parsing base64 String...
var binaryString = window.atob(data);
var binaryLen = binaryString.length;
var fileContent = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
fileContent[i] = ascii;
}
var blob = new Blob([fileContent], { type: 'application/octet-stream' }); //octet-stream
var fileURL = window.URL.createObjectURL(blob);
$sce.trustAsResourceUrl(fileURL); //allow angular to trust this url
//Creating the anchor download link
var anchor = angular.element('<a/>');
anchor.css({display: 'none'}); // Make sure it's not visible
angular.element(document.body).append(anchor); // Attach it to the document
anchor.attr({
href: fileURL,
target: '_blank',
download: fileName
})[0].click();
anchor.remove(); // Clean it up afterwards
})
//.error(function(...
And On your backend, make sure that your webservice produces octet-stream and returning the file in base64 data format, i did this using Java JAX-RS like this:
#POST
#Path("/downloadfile")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(...){
String base64String = Base64.getEncoder().encodeToString(/*here you pass your file in byte[] format*/);
return Response.ok(base64String).build();
}

Not able to expose the custom headers from WebAPI to client

I have written a program to download the pdf, word or txt file returned by web api and it's working fine. On server side I have used WebApi and client side AngularJs. Now the problem is, I also need the file name from api as well and for that I need to read the headers returned by api. But reponse.headers doesn't contains all the headers info. Below is my code:
[HttpGet]
[Authorize]
public HttpResponseMessage GetTranscript(string key, int format)
{
var badRequest = Request.CreateResponse(HttpStatusCode.OK, "Not a valid input."); //ResponseMessage(Request.CreateResponse(HttpStatusCode.BadRequest, "Not a valid input."));
if (string.IsNullOrWhiteSpace(jiraTaskKey))
{
return badRequest;
}
string transcript = _mediaCaptionService.GetTranscript(UserId, key);
string fileName = "transcript";
var response = new HttpResponseMessage(HttpStatusCode.OK);
if (format == (int)TranscriptFormat.PDF)
{
byte[] byteInfo = GeneratePDFTranscript(transcript);
response.Content = new ByteArrayContent(byteInfo);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
fileName = fileName + ".pdf";
}
else if (format == (int)TranscriptFormat.TXT)
{
response.Content = new StringContent(transcript, System.Text.Encoding.UTF8, "text/plain");
fileName = fileName + ".txt";
}
else if (format == (int)TranscriptFormat.WORD)
{
string transcriptFontName = "Arial";
byte[] byteInfo = GenerateWordTranscript(transcript, transcriptFontName);
response.Content = new ByteArrayContent(byteInfo);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
fileName = fileName + ".doc";
}
else
{
return badRequest;
}
response.Content.Headers.Add("x-filename", fileName);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = fileName
};
//response.Content.Headers.ContentDisposition.FileName = fileName;
return response; //ResponseMessage(response);
}
and in client side
function getTranscriptResult(method, apiUrl, data) {
var deferred = $q.defer();
$http({
method: method,
url: apiUrl,
data: data,
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
debugger;
var results = [];
results.data = data;
results.headers = headers();
results.status = status;
results.config = config;
deferred.resolve(results);
}).error(function (error, status, headers, config) {
deferred.reject(error);
});
return deferred.promise;
}
But when I put the break point in above code, I get this:
Can you please tell me where is the problem in my code that I am not able to get the file name? Also please let me know if you need more information.
After adding below lines has solved my problem.
// Add a custom header for filename and expose it to be consumed by JavaScript.
response.Content.Headers.Add("Filename", zipFileName);
response.Content.Headers.Add("Access-Control-Expose-Headers", "Filename");
So basically adding Access-Control-Expose-Headers helped me to expose the custom headers to client. For more information on this please follow this link

Resources