I am currently working in angular 6. i have to download pdf file from bytearray.
when i tried to download an pdf file. it downloads but when i open it. it shows error. please help me with it.
In the download.component.ts i am getting response as two values. first pdfname, second pdfbytearray. i am getting those values from component response.
sample response:
{
pdfName: "test.pdf",
pdfByteArray: "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9Qcm9kdWNlcij"
}
download.service.ts:
generatePdf(id) {
const httpOptions = {
'responseType': 'arraybuffer' as 'json'
};
return this.http.post<any>(URL.BASE_URL + 'application/generate?id='+ id,
{ httpOptions },
);
}
download.component.ts:
import { saveAs } from 'file-saver/FileSaver';
generatePdf() {
this.downloadApiService.generatePdf('4')
.subscribe( pdf => {
console.log('pdf response: ', pdf);
var mediaType = 'application/pdf';
var blob = new Blob([pdf.pdfByteArray], {type: mediaType});
let fileName = pdf.pdfName;
saveAs(blob, fileName);
}, err => {
console.log('Pdf generated err: ', JSON.stringify(err));
});
}
Related
I am downloading a pdf file from API, but I am getting a blank PDF. I have tested the API endpoint and able to get the byte stream on the console and when I save it to File, it got saved and the file looks good. Getting the same response back to the front end using React and I could see the PDF byte stream in the response.
However, I could not see the content. It says the file is damaged or corrupted when I opened the downloaded PDF from my local.
I have looked at many examples and are following the same pattern, but I think I am missing something here.
My API Java endpoint definition looks like below
#GetMapping(value = "/fetchFile")
public ResponseEntity<byte[]> fetchFile(#RequestParam final String key) {
FileResponse response = myService.readFile(key);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + key.substring(key.lastIndexOf('/') + 1) + "\"");
return Mono.just(ResponseEntity.ok().headers(httpHeaders).contentLength(response.getContentLength())
.contentType(MediaType.parseMediaType(response.getContentType()))
.body(response.getResponseBytes()));
}
Frontend:
rounterFetchFile.js
router.get('/', (request, resp) => {
axios({
method: 'get',
baseURL: 'http://mybackend.apibase.url',
responseType: 'blob',
url: '/fetchFile',
params: {
fileKey: 'myfile.pdf'
}
})
.then(response => {
return resp.send(response.data)
})
.catch(error => {
console.error(error)
return resp.status(error.response.status).end()
})
})
in myFileComoponent.js
//a function that reads the response from rounterFetchFile.js
const getDocumentOnClick = async () => {
try {
var {data} = await pullMyPDF()
var blob = new Blob([data], { type: "application/pdf" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "myFileName.pdf";
link.click();
} catch (e) {
console.log(e)
}
}
Here
var {data} = await pullMyPDF()
is returning the following content. I compared it with the result returned by the Postman, and it is the same. The generated file size is not empty from the react too. I am not able to find out where is it wrong
Below is the response from API endpoint for the fetchFile
I had a similar problem and I fixed it with this:
spa
axios.post(
'api-url',
formData,
{
responseType: 'blob',
headers: {
'Accept': 'application/pdf'
}
})
.then( response => {
const url = URL.createObjectURL(response.data);
this.setState({
filePath: url,
fileType: 'pdf',
})
})
.catch(function (error) {
console.log(error);
});
api
[HttpPost]
public async Task<IActionResult> Post()
{
var request = HttpContext.Request;
var pdfByteArray = await convertToPdfService.ConvertWordStreamToPdfByteArray(request.Form.Files[0], "application/msword");
return File(pdfByteArray, "application/pdf");
}
When the response type is a blob and accepted 'application / pdf' in the header, with that config the job is done ;) ...
Something that worked for me was to send the bytes as base64 from the controller.
API:
public async Task<ActionResult> GetAsync() {
var documentBytes = await GetDocumentAsync().ConfigureAwait(false);
return Ok(Convert.ToBase64String(documentBytes))
}
Front End:
client.get(url, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => {
const link = document.createElement('a');
link.href = "data:application/octet-stream;base64," + response.data;
link.download = 'file.pdf';
link.click();
})
.catch(error => {
console.log(error);
})
I hope this solves your problem.
I have a problem with the PDF file I get from the API in response to a Json GET request.
It does get a good string in Json, however, which makes the PDF file that appears corrupted. I tried to convert the response to a string but it didn't do anything.
Here is my code:
getPDF() {
axios
.get(apiurl + "api/Dok", { params: { }, headers: { } })
.then(response => {
const res = response.data.fileData;
const pdfcode = res.toString();
this.convertPDF(pdfcode)
}
)
.catch(error => {
alert('error')
});
}
convertPDF(value) {
const file = new Blob(
[value],
{type: 'application/pdf'});
const fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
So if i'm import the pdf file from local and add it to this function istead of url in console i'm getting long string response
JVBERi0xLjUNCjQgMCBvYmoNCjw8L1R5cGUgL1BhZ2UvUGFyZW50IDMgMCBSL0NvbnRlbnRzIDUgMCBSL01lZGlhQ...
and PDF works, but when get it from URL i'm getting :
{"fileData":"JVBERi0xLjUNCjQgMCBvYmoNCjw8L1R5cGUgL1BhZ2UvUGFyZW50...
I checked it in notepad, the first answer and the content of "" are identical
any ideas what i can do?
i'm trying to download a pdf report (using jasperReports) directly from browser...
my JS code is above:
if (generateReport) {
Loader.get(`${window.location.origin}/api/${Version.TRIP}/expenses/report-analytics?${getUrlParamsForReport(entity)}`).then(response => {
const file = new Blob([response.data], { type: 'application/pdf' });
const fileURL = URL.createObjectURL(file);
window.open(fileURL, "EPrescription");
}).catch((error) => {
SnackbarController.add({
description: error.message,
duration: 3000,
});
Promise.reject(onError(error));
});
}
in my java code, the response is:
return bos.toByteArray();
pdf opens but has no content, no header, nothing!!
help?
UPDATED with res.send(data) instead of res.json(data)
Using Angular 6 and NodeJS I am doing a web application.
I am trying to download a file from a http post request.
I send a request to the server like this. From my component I call a function in a service. In the component, I susbscribe to have the answer of the server and when I have it I create a new Blob with the response and I Use FileSaver to download the pdf.
Now, when I received the answer from the server, the client sees it like an error whereas the status is 200. The error message is:
"Http failure during parsing for http://localhost:3000/api/experiment/regression"
See the screenshot below.
Component.ts
this.api.postML(this.regression).subscribe(
res => {
console.log(res);
let pdf = new Blob(res.data, { type: "application/pdf" });
let filename = "test.pdf";
FileSaver.saveAs(pdf, filename);
},
err => {
alert("Error to perform the regression");
console.log(err);
}
);
API.Service.ts
public postML(data): Observable<any> {
// Create url
let url = `${baseUrl}${"experiment/regression"}`;
let options = {
headers: { "Content-Type": "application/json", Accept: "application/pdf" }
};
// Call the http POST
return this.http
.post(url, data, options)
.pipe(catchError(this.handleError));
}
Then from the server, it executes some code with the data sent and generates a PDF file.
Then, I would like to send the pdf as a response to the client.
I tried like this:
fs.readFile("/home/user/test.pdf", function(err, data) {
let pdfName = "Report.pdf";
res.contentType("application/pdf");
res.set("Content-Disposition", pdfName);
res.set("Content-Transfer-Encoding", "binary");
console.log(data);
console.log("Send data");
res.status(200);
res.send(data);
});
In the client, I have the answer. The console log is:
Finally, I found a video tutorial and it was very basic.
Node.js Server:
const express = require("express");
const router = express.Router();
router.post("/experiment/resultML/downloadReport",downloadReport);
const downloadReport = function(req, res) {
res.sendFile(req.body.filename);
};
Angular Component:
import { saveAs } from "file-saver";
...
download() {
let filename = "/Path/to/your/report.pdf";
this.api.downloadReport(filename).subscribe(
data => {
saveAs(data, filename);
},
err => {
alert("Problem while downloading the file.");
console.error(err);
}
);
}
Angular Service:
public downloadReport(file): Observable<any> {
// Create url
let url = `${baseUrl}${"/experiment/resultML/downloadReport"}`;
var body = { filename: file };
return this.http.post(url, body, {
responseType: "blob",
headers: new HttpHeaders().append("Content-Type", "application/json")
});
}
I have a Node JS Rest get service which send the zip folder created on my server in binary encoded format. But unable to download this on client. I am unable to open the zip.
Server controller
botsController.exportBot = (req,res) =>{
let botId = req.params.botId;
zipFolder("...pathtoZip/", "pathToFolder/my.zip", function(err) {
if(err) {
res.statusCode = 500;
return res.send({
success: false,
message: "Something went wrong while fetching the bot data",
err_details: err
});
} else {
let filetext;
let zipFolder= "pathToFolder/my.zip";
if (fs.existsSync(zipFolder)) {
filetext = fs.readFileSync(zipFolder, "utf-8");//tried encoding binary
}
var headers = {
'Content-Type': 'application/octet-stream',//tried application/zip
'Content-Disposition': "attachment; filename=" + botId + '.zip'
};
res.writeHead(200, headers);
return res.end(filetext,"binary");
}
});
And on angular js Service I have fetch the data. And on component I have downloaded it.But download zip is corrupted it gives error unable to open the zip.
Angular 2 Service
exportBot() {
let token = localStorage.token;
let headerObj = {
'Authorization': token,
responseType: ResponseContentType.ArrayBuffer
};
let headers = new Headers(headerObj);
return this.http.get("export/botId", { headers: headers })
.map((res) => new Blob([res['_body']], { type: 'application/zip' }))
.catch(this.errorHandler);
}
And on component end
exportBot() {
this.loader = false;
this.botdataservice.exportBot()
.subscribe(res => {
console.log(`excel data: ${res}`);
window.open(window.URL.createObjectURL(res));
},
err => {
console.log(err);
})
}
In your package.json add the dependency :
"file-saver": "^1.3.3",
And you can use the file saver on your get request as below :
public getBlob(url: string): Observable<Blob> {
this.showLoader();
return this.http.get(url, {responseType: 'blob'})
.catch(this.onCatch)
.do(res => {
this.onSuccess(res);
}, (error: any) => {
this.onError(error);
})
.finally(() => {
this.onEnd();
});
}
and the method to download :
downloadFile(fileid: string) {
return this._http.getBlob(this._http.backendURL.downloadFile.replace(':fileid', fileid))
}
And the you call the Filesaver when subscribing data as this :
downloadFile() {
this._downloadFileService.downloadFile(this.model.fileid)
.subscribe(
data => {
FileSaver.saveAs(data, this.form.getRawValue().title);
}
);
}
I hope this can help.
You can convert your file to base64 by using btoa(unescape(encodeURIComponent(binarydata))) or in case of array buffer try btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
Either can even send base64 file from your node server
filetext = fs.readFileSync(zipFolder);
return res.end(new Buffer(filetext ).toString('base64'));
in that case change your headers
and use following code to download it
var base64Str = "UEsDBAoAAgAAAMWqM0z4bm0cBQAAAAUAAAAJAAAAdmlub2QudHh0dmlub2RQSwECFAAKAAIAAADFqjNM+G5tHAUAAAAFAAAACQAkAAAAAAABACAAAAAAAAAAdmlub2QudHh0CgAgAAAAAAABABgAUCMddj2R0wFA/Bx2PZHTAWCGE3Y9kdMBUEsFBgAAAAABAAEAWwAAACwAAAAAAA==";
var elem = window.document.createElement('a');
elem.href = "data:application/zip;base64,"+base64Str
elem.download = "my.zip";
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);