How can i download the pdf directly from the API (Angular)? - javascript

I need to download a PDF from an API in Angular.
So, I've written a service to call the API:
getPDF(id:any) {
return this.http.get(
`url?=${id}`,
{ responseType: 'blob' as 'json', observe: 'response' }
);
}
In my component file, I'm calling the service to download the PDF.
onGeneratepdf() {
this.service
.getPDF(
123
)
.subscribe((res: any) => {
let filename = res.header
?.get('content-disposition')
?.split(';')[1]
.split('=')[1];
let blob: Blob = res.body as Blob;
var a = document.createElement('a');
a.download = filename;
a.href = window.URL.createObjectURL(blob);
a.click();
});
}
after hitting onGeneratePDF , the pdf is downloading but the problem is ....it is downloading the file name as undefined.pdf...it should download as name like user.pdf and also
i am getting the response headers as
access-control-allow-origin: *
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-disposition: attachment; filename=user.pdf
content-type: application/pdf
Please help me on these issue.
Thanks in advance.

onGeneratepdf() {
this.service
.getPDF(
123
)
.subscribe((res: any) => {
let filename = res.headers
?.get('content-disposition')
?.split(';')[1]
.split('=')[1];
let blob: Blob = res.body as Blob;
var a = document.createElement('a');
a.download = filename;
a.href = window.URL.createObjectURL(blob);
a.click();
});
Please try above code, you wrote res.header that should be res.headers
if above code not works for you, then take look at below link you will find your solution there Here.
Thanks!

Related

When I open a Salesforce Attachment it is downloaded but the pdf is empty

I am getting the attachment body using the Rest API.
var config = {
method: 'get',
url: '<Domanin>/services/data/v48.0/sobjects/Attachment/00PD000000HQD68MAH/Body',
headers: {
'Authorization': `Bearer ${
accessToken
}`,
'content-type':'application/pdf'
},
};
let rawData = await axios(config);
rawData = rawData.data
I am getting the PDF data in this format
%PDF-1.5
%ÓôÌá
1 0 obj
<<
In the client side I am trying to make this as a downloadable file but I am getting blank pdf. The actual pdf contains 2 pages the downloaded pdf contains two pages as well but they are blank.
Client Side Code:
var downloadLink = document.createElement('a');
downloadLink.target = '_blank';
downloadLink.download = 'test.pdf';
// convert downloaded data to a Blob
var blob = new Blob(([rawData]), {type: 'application/pdf'});
// create an object URL from the Blob
var downloadUrl = URL.createObjectURL(blob);
// set object URL as the anchor's href
downloadLink.href = downloadUrl;
// append the anchor to document body
document.body.append(downloadLink);
// fire a click event on the anchor
downloadLink.click();
Please let me know what is wrong with the above logic
Please specify responseType: 'arraybuffer' in request config. Modify your config object to
{
method: 'get',
url: '<Domanin>/services/data/v48.0/sobjects/Attachment/00PD000000HQD68MAH/Body',
headers: {
'Authorization': `Bearer ${
accessToken
}`
},
'responseType': 'arraybuffer'
};

How to download big file with stream and JWT in Javascript?

I want to download a zip file with a size of 300mb, I do it in Node.js with stream (so the download is byte by byte).
request('https://...').pipe(res);
The problem is I need to send a token to download this file in the header.
How to do it? Because I try to do it with this code:
let a = document.createElement('a');
a.href = `/api/download`;
a.target = '_blank';
a.download = 'test.zip';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
console.log('done');
It works when I turn off the token required. (but I need to send this token).
I also try this code:
axios({
url: 'http://localhost:5000/api/download',
method: 'GET',
responseType: 'blob', // important
headers: {
Authorization: "Bearer <insert_your_JWT_here>"
}
}).then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'file.zip');
document.body.appendChild(link);
link.click();
});
But what this does is download the file (300mb) and after it's downloaded, it begins to download to the disk (this is bad).
So, how to download file as stream and with token?
So, in your code i don't see place where you keep your token.
You can use bearer
Try simple example:
axios({
url: 'http://localhost:5000/api/download',
method: 'GET',
responseType: 'blob', // important
headers: {
Authorization: "Bearer <insert_your_JWT_here>"
}
}).then((response) => {
//your code
});

Axios download file by the generated filename from the backend

I am using Axios to send POST request to my backend.
The backend generate an Excel file with a name e.g. testing.xlsx.
What I am trying to do:
Doing this file using the same filename generated from the backend and I have tried Postman and everything works fine.
What I have tried:
axios.post(`${env.ENDPOINT}reports/sales/customers_statement`, {
customers_id: form_data.customers_id,
from_date: form_data.from_date,
to_date: form_data.to_date,
},{
responseType: 'blob'
}).then((res) => {
const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
const file_name = `${new Date().toISOString().slice(0,10)}.xlsx`; // RENAME HERE
link.href = url;
link.setAttribute('download', file_name);
document.body.appendChild(link);
link.click();
resolve(res.data);
}).catch((e) => {
reject(e);
});
This works fine but it doesn't download the file by the filename generated from the server.
In other words I want to send request to my backend to download the file by the file name already generated from my backend like when I send request using Postman.
It is because you are setting the download attribute to file_name value which is different from the filename server returned
const file_name = `${new Date().toISOString().slice(0,10)}.xlsx`;
Try changing the above to this
const contentDisposition = data.headers['content-disposition'];
const filename = contentDisposition.match(/filename=(?<filename>[^,;]+);/)[0];
link.setAttribute('download', file_name);
In the backend
response.setHeader("Content-disposition", "attachment; filename="+ yourfilenamehere);

res.download() download window not showing up

I created a download button that downloads the file on click. The problem is when I click the download button, I'm able to see the content that I want to download by using Chrome inspect -> Network -> Response but it is not opening a window to save the file to my PC.
For example, I'm trying to download text.txt which contains multiple lines of MY FILE string. I'm able to see it on Response tab but how can I download the .txt file.
Relevant React Code:
<button onClick={(e) => downloadHandler(e)}>Download</button>
let downloadHandler = (e) =>{
const fileName = e.target.parentElement.id;
fetch('http://localhost:3001/download',{
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({id: fileName})
})
}
Relevant Backend Code:
const uploadFolder = `${__dirname}` + `\\uploads\\`;
app.post('/download', function(req, res){
let fileName = req.body.id; // example output: 'dog.jpg'
res.download(uploadFolder+fileName, fileName); // Set disposition and send it.
});
The idea is that I will feed fileName to backend and then download it with res.download(uploadFolder+fileName, fileName); line. I think im suppose to use window.open('/download') but that just opens the homepage on a new tab or maybe I am just placing it wrong.
Okay, I have managed to solve my issue. three main modifications were made to make this code and idea work.
Changing the request from POST to GET. Another
StackOverflow thread also mentions this.
Using axios() instead of fetch().
Creating Blob object from the res.download(filePath, fileName) response value.
Anyone else having this problem with the React Code part should check this Github link.
Final State of the React function posted in the question
let downloadHandler = (e) =>{
const fileName = e.target.parentElement.id;
axios({
method: 'get',
url: 'http://localhost:3001/download/'+fileName,
responseType: 'blob',
headers: {},
})
.then((res) => {
const url = window.URL.createObjectURL(new Blob([res.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
})
.catch((error) => {
alert(error);
})
}
Final State of the backend code posted in the question
const uploadFolder = `${__dirname}` + `\\uploads\\`;
app.get('/download/:filename', function(req, res){
let fileName = req.params.filename
const filePath = uploadFolder+fileName;
res.download(filePath, fileName);
});

Download File automatically with browser that can be opened or read properly

Frontend will send a post request to Scala Play Framework API to download a file. The response header is like :
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:8000
Content-Disposition:attachment;
filename="logo_10248191299068944166699.png";
filename*=utf-8'logo_10248191299068944166699.png
Content-Length:53765
Content-Type:image/png
Date:Thu, 07 Sep 2017 13:05:57 GMT
Vary:Origin
My react js code is as below:
const FileDownload = require('react-file-download')
axios(req).then(response => (response.status === 200? response :
null)).then(res =>
{
FileDownload(res.data, filename)
})
It can be downloaded automatically but the file cannot be read. For example, if I download an image, the image cannot be rendered. If I download a zip file, it cannot be extracted. I already tried React-FileDownload, FileSaver, convert the res.data into arraybuffer with the creation of 8 bit array for loop - I.Just.Cant.Make.It.Work.
When I erase the extension format from ubuntu and open it on Atom, these shows up. And from the download tab in Chrome, it stated blob:http://localhost:8000/4de5d808-67a6-4d4e-9920-24bd342664f6
�PNG
IHDRwB���gAMA���asRGB���
cHRMz&�����u0�`:�p��Q<bKGD�������
pHYs.#.#x�?v�IDATx���w�e�Y����9WܹrN]]�-����0�2��,����t|
�=w�{ƹ�&����`LI��`0&I�J��j�����}��J���Pa�=W�~����ݭ��jϵ~�}��1`�|�;��֟zQj�?xz�����z�N-�^n5��$�m�:Uv��Sv�]�N��%=✾s����V��Ǜ?l����>$)��7��p�y{B]]�Ò�T��J:i�̥���+.�V5����$����u����u^�����-��%��tJ��ً�[��8��$}���UOI�{޻]v��N�3k׉�I�!�+$}�����I'���cW���_sNF�DҏI�Ip�9��$�`��
I solved the problem. It lies in the POST request.
url: url + '/storage/download_file',
method: 'POST',
responseType: 'blob', //THE KEY TO SUCCESS
headers: {
Authorization: 'Bearer ' + token,
Accept: 'application/json',
'Content-Type': 'application/json'
}
Have to add responseType: 'blob'
I changed to FileSaver to download file.
var blob = new Blob([res.data], {type: "application/octet-stream"});
FileSaver.saveAs(blob, filename)
Solution above is working but I don't like to install excessive packages
Axios
url: '/url
responseType: 'blob'
JS
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.href = url;
link.download = fileName;
document.body.appendChild(link); // optional
link.click();
document.body.removeChild(link); // optional

Categories

Resources