Axios download file by the generated filename from the backend - javascript

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);

Related

AWS .tgs file is downloaded as a .gz archive (aws, js)

I am uploading files to s3 in this way.
This is the server code:
const params = {
Bucket: `${process.env.AWS_FOLDER_NAME}/${bucketName}`,
Key: fileName,
ContentType: fileType,
ACL:'public-read'
}
const signedUrl = s3.getSignedUrl('putObject', params)
return signedUrl
This is the client code:
const {signedUrl, err} = await response.json()
await fetch(signedUrl, {
method: 'PUT',
body: file.body,
headers: {
'Content-Type': file.fileType,
'x-amz-acl': 'public-read',
}})
.catch(err => {
console.log(err)
})
Here file.body is reader.result from this code
const reader = new FileReader()
reader.onload = () => resolve(reader.result)
reader.onerror = reject;
reader.readAsArrayBuffer(file);
All this works very well! But yesterday I uploaded a .tgs file in this way (it's a telegram sticker) and when I try to download it from s3, I don't download the file itself.
Instead this, s3 give me the .gz archive inside which my original .tgs file lies. Moreover, this is a file inside the .gz archive without the .tgs extension.
The file itself in s3 looks quite normal
I want s3 to just give me the file. How should I do it?
tgs file is actually a gz file, you can just rename it from AnimatedSticker.gz to AnimatedSticker.tgs

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'
};

Multipart form Response from NodeJS Server- issue extracting some fields

I have a ReactJS Application that sends an Axios POST request to a NodeJS express server and expects a response with several fields. Specifically, I am using "form-data" in the backend to handle the data streaming.
Here is my backend response.
var FormData = require('form-data');
app.get('/test', (req, res) => {
// create a new form to send all data back to client
var form = new FormData();
form.append('results_log', 'this is text', { contentType: 'text/plain'});
form.append('results_images', fs.createReadStream('./test_results/result.zip'), { contentType: 'application/zip' });
console.log(form);
form.pipe(res);
});
In the frontend, I can download the "results_images" ZIP file from the formdata server response without any issues, but I cannot get the "results_log" field, which is just a simple string. Every attempt has resulted in a "null".
Below is the frontend code.
axios({
url: 'http://localhost:5000/test',
method: 'GET'
})
.then((response) => {
var info = response;
// this alerts NULL
alert(info.data["results_log"]);
const url = window.URL
.createObjectURL(new Blob([info.data["results_images"]]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'results.zip');
document.body.appendChild(link);
link.click();
})
.catch((error) => console.log(error));
Here is part of the alert of the whole response.data field. As you can see, both fields are present in the response.
Am I doing something wrong when extracting the string field? Any help is appreciated!

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