downloading blank pdf when using express to call looker api - node.js

When calling render_task_results(render_task_id) looker API from my NodeJS based API using axios I am getting the binary data but when downloading it it is giving me blank PDF.
PFB my code.
const response = await createPdf(TaskID, lookerToken.access_token);
res.set({ 'Content-Type': 'application/pdf', 'Access-Control-Allow-Origin': '*' });
res.status(200).send(response.body);
return res;
export async function createPdf(TaskID, lookerToken): Promise<any> {
return new Promise((resolve) => {
const url = "someurl/api/3.1/render_tasks/" + TaskID + '/results';
const headers = {
'Authorization': 'token ' + lookerToken
};
axios({
headers,
method: 'get',
url: url,
responseType: 'blob'
}).then((response: any) => {
resolve({
body: response.data
//statusCode: response.status,
});
})
});
}

Related

Fetching API and setting a variable to the res

const fetch = require('node-fetch');
let body = { a: 1 };
const stopId = 413
fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(json => body = json);
console.log(body)
I'm getting the output: { a: 1 } Instead of the API JsonResponse, however when I use .then(json => console.log(json)); I get the desired response..
I've tried to use await fetch, to pause the code till the promise returned then to console.log body but it needs to be an async function.. Does anyone know how I can assign the let body a new value before proceeding to the code below? Or would there be a way to return from .then ?
So I could do something like: (I know this doesn't work)
function fetchStop(stopId){
fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(json => return body);
}
console.log(fetchStop(stopId))
Any solutions or explanations/insights on how these things work is much appreciated, very much a noob with async and promises
The fetch executes asynchronously and you can access the result only in the callback.
Here, the console.log(body) executes soon after a network call is initiated.
const fetch = require('node-fetch');
let body = { a: 1 };
const stopId = 413
fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(json => body = json);
console.log(body)
To access the result,
function fetchStop(stopId){
return fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
}
fetchStop(stopId).then(result => console.log(result))
You are using promise for fetching data from your URL https://api.ashx?stopId=${stopId}. Since this will take time and is asynchronous (nonblocking) so while it is fetching data code will move to console.log(body) and print the previous body (body = { a: 1 };). Because code flow moves to console.log before the promise gets executed, this promise will take time to fetch data. So you have to console.log within then itself. Because that's the point when your promise is getting executed later in time. You can do it easily using async await
const yourFunction = async () => {
const fetch = require('node-fetch');
let body = { a: 1 };
const stopId = 413;
const { hostname: location } = window.location;
const data = {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
}
const response = await fetch(`https://api.ashx?stopId=${stopId}`, data);
if (!response.ok) throw Error(response.message);
try {
body = await response.json();
return;
} catch (err) {
throw err;
}
};

Axios FormAppend post method and node.js

I trigger / upload in node.js by calling the submit function inside a class. But in Node.js, req.body is empty. In fact, I append data to FormData in the submit function and send it to node.js. Where am I doing the problem?
Class
submit(){
const data = new FormData()
data.append('file', this.state.selectedFile)
data.append('ID', uniqid())
let url = "http://localhost:5000/upload";
axios({
method: "POST",
url: url,
data: data,
headers: {
"Content-Type": "application/json"
}
}).then(res => {
});
}
Node.js
app.post('/upload', (req, res) => {
axios.post('https://....php', req.body, {
}).then(function (response) {
}).catch(function (error) {
console.log('errorserver', error);
});
});
Try to put file after text like this.
submit(){
const data = new FormData()
data.append('ID', uniqid())
data.append('file', this.state.selectedFile)
let url = "http://localhost:5000/upload";
axios({
method: "POST",
url: url,
data: data,
headers: {
"Content-Type": "application/json"
}
}).then(res => {
});
}

How to save a PDF from an REST API call

I am sending a request to a server via axios. In response I get this code from server. I think it is buffer type thing. Dont't know anything about it.
%PDF-1.3\n' +
'%����\n' +
'1 0 obj\n' +
'<<\n' +
' /CreationDate (D:20201204055104Z)\n' +
' /ModDate (D:20201204055104Z)\n' +
'>>\n' +
'endobj\n' +
'2 0 obj\n' +
I want to save this response in pdf format. I have tried this code but it will only generate blank pdf file.
Here is my code
const url = "https://api-stage-starfleet.delhivery.com/package/DL000246845CN/shipping-label";
// Headers config
const config = {
headers: {
'Accept': 'application/pdf',
'id_token': id_token,
'Authorization': auth_token,
}
}
axios.get(url, config)
.then((response) => {
fs.writeFile("output.pdf", response.data, function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
})
.catch((err) => {
console.log(err);
})
I have also tried by adding encoding in header object. But it is not working and only generating blank pdf. Can anyone help me on this.
By default, axios will use strings for its response types. In order to tell it to use binary data instead you pass a configuration called responseType:
const config = {
headers: {
'Accept': 'application/pdf',
'id_token': id_token,
'Authorization': auth_token,
},
responseType: 'buffer'; // <-- Here -----
}
Then, your writeFile would work, though note it's far more efficient to just pipe the response from axios to the file:
axios({
method: "get",
headers: {
'Accept': 'application/pdf',
'id_token': id_token,
'Authorization': auth_token,
},
responseType: "stream"
}).then(function (response) {
response.data.pipe(fs.createWriteStream("output.pdf"));
});

'Axios' show Error: Network Error on server returning with 200 http status

I am using axios: "^0.19.0" to create get and post requests in react-native 0.60.4, but even after backend returning HTTP status code 200 axois showing Error: Network Error. Working perfectly on iOS but not on Android.
My request:
export default function uploadImageWithData(formData, url = "createGroup") {
return new Promise((resolve, reject) => {
axios({
method: "post",
url: BASEURL + "api/webservice/" + url,
data: formData,
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${global.authToken}`
}
})
.then(response => {
resolve(response);
})
.catch(err => {
console.log("error: ", err);
reject(err);
});
});
}
Kindly help.
The issue with formData, in formData empty array appending in formData causing the issue(For Android).

Cloudconvert - Invalid signature error when using request-promise to upload via API

I'm attempting to upload a pdf through the cloudconvert API using nodeJS and request-promise. The request to get the upload URL and parameters is successful, but when I attempt to pass the data I get a 401 - "FormPost: Invalid Signature" error, even though I'm using the signature returned from the first request.
...
pdfToPng: function(pdfBuffer, apiKey) {
return new Promise(async (resolve, reject) => {
const cloudConvert = new CloudConvert(apiKey);
let response = JSON.parse(
await request.post('https://api.cloudconvert.com/v2/import/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-type': 'application/json',
},
}));
let fileUrl = response.data.result.form.url;
let params = response.data.result.form.parameters;
let fileUpload = await request.post({
url: fileUrl,
formData: {
"expires": params.expires,
"max_file_count": params.max_file_count,
"max_file_size": params.max_file_size,
"signature": params.signature,
"file": {
value: pdfBuffer.toString('base64'),
options: {
filename: 'invoice.pdf',
contentType: 'application/pdf'
}
}
}
}).catch((err) => {
console.log('ERROR UPLOADING FILE: ', err); //<-- 401 Error here
reject(err);
})
console.log('FILE UPLOAD RESPONSE: ', fileUpload);
...
You need to pass all parameters of response.data.result.form.parameters to formData, not just the named ones:
let fileUpload = await request.post({
url: fileUrl,
formData: {
...response.data.result.form.parameters,
"file": {
value: pdfBuffer.toString('base64'),
options: {
filename: 'invoice.pdf',
contentType: 'application/pdf'
}
}
}

Resources