request body characters showing ? using fetch or request from quickbooks - node.js

I am using quickbooks api in a node 10.16 environment.
I am trying to get the PDF through the API.
I am getting what looks like the correct response but when I open it it shows blank
I have downloaded a file using postman directly and that file works.
I have opened both files up using notepad++ and I can see some characters on my file have ? or a square where on the postman file I see a character.
This google folder has both files
This is the main code where I grab the information from the API using fetch
return fetch(url, fetchOptions).then((response) => {
if (response.ok) {
return response.text()
}
response.text() is where the bad decoding is happening because I have saved it directly to a file or tried decoding it with TextDecoder and it always gives me bad characters.
Here is what I have tested so far
return response.arrayBuffer().then(buffer => {
let decodedValue = new util.TextDecoder('utf-8').decode(buffer)
fs.writeFile('decodetest.pdf', decodedValue, (err) => {
// throws an error, you could also catch it here
if (err) throw err;
// success case, the file was saved
console.log('decode file saved!');
});
return decodedValue;
});
rp below is using a different package response-promise. Also giving the same results.
return rp(options)
.then(function (response) {
console.log("Did a new response");
response.body
fs.writeFile('requesttest.pdf', response.body, (err) => {
// throws an error, you could also catch it here
if (err) throw err;
// success case, the file was saved
console.log('request test file saved!');
});
})
.catch(function (err) {
// Delete failed...
});

Related

Formidable using "end" event with file upload

I am using Formidable with Express in nodeJS in an attempt to have a simple single file upload scheme. I have confirmed that a file is actually sent over from the client-side, but where it seems to run into troubles is on the server-side.
index.js
app.post('/', (req, res) => {
const form = formidale();
form.on('file', (filename, file) => {
fs.rename(file.path, `./data/nodes.csv`, err => {
if (err) {
console.log(`There was an error in downloading a CSV file: ${err}`);
return null;
}
else {
console.log("CSV file has been uploaded correctly.");
}
});
});
form.on('error', err => {
console.log(`There was an error in downloading a CSV file: ${err}`);
return null;
});
form.on('end', () => {
console.log(fs.readFileSync('./data/nodes.csv')); // test to see if file exists
const nodes = assignMetrics();
console.log(nodes);
return nodes;
});
form.parse(req);
});
}
The main trouble I seem to find is that the form.on('end', ...) event does not seem to wait till the file has finished uploading to fire. I have confirmed this by trying to read the file in the event, but by that point it doesn't exist? The documentation though appears to suggest it is only meant to fire "after all files have been flushed [from the APIs pipe it infers]".
There appears to be no other events available that might wait till the file has been uploaded to be called? I also don't want to start throwing in layers of promises and such unless it is the only option, as each new layer of promises I find is a chance for unintended effects to happen.

Google drive API downloading file nodejs

Im trying to get the contents of a file using the google drive API v3 in node.js.
I read in this documentation I get a stream back from drive.files.get({fileId, alt: 'media'})but that isn't the case. I get a promise back.
https://developers.google.com/drive/api/v3/manage-downloads
Can someone tell me how I can get a stream from that method?
I believe your goal and situation as follows.
You want to retrieve the steam type from the method of drive.files.get.
You want to achieve this using googleapis with Node.js.
You have already done the authorization process for using Drive API.
For this, how about this answer? In this case, please use responseType. Ref
Pattern 1:
In this pattern, the file is downloaded as the stream type and it is saved as a file.
Sample script:
var dest = fs.createWriteStream("###"); // Please set the filename of the saved file.
drive.files.get(
{fileId: id, alt: "media"},
{responseType: "stream"},
(err, {data}) => {
if (err) {
console.log(err);
return;
}
data
.on("end", () => console.log("Done."))
.on("error", (err) => {
console.log(err);
return process.exit();
})
.pipe(dest);
}
);
Pattern 2:
In this pattern, the file is downloaded as the stream type and it is put to the buffer.
Sample script:
drive.files.get(
{fileId: id, alt: "media",},
{responseType: "stream"},
(err, { data }) => {
if (err) {
console.log(err);
return;
}
let buf = [];
data.on("data", (e) => buf.push(e));
data.on("end", () => {
const buffer = Buffer.concat(buf);
console.log(buffer);
});
}
);
Reference:
Google APIs Node.js Client

Unable to send photo using Form Submit

I've a photo and a paid upload service : http://example.com/in.php .
I'm not able to upload a given jpeg file using this code. It is telling me that invalid file format uploaded. But using file linux command I can see it is JPEG format. Is there any problem in this code?
fs.readFile('/tmp/photo.jpg'', 'utf8', function(err, contents) {
var b64 = new Buffer(contents);
var s = b64.toString('base64');
var request = require('request')
request.post('http://example.com/in.php', {
form: {
method:'base64',
key:'cplbhvnmvdn4bjxxchzgqyjz7rf9fy8w',
body:s,
}
}, function (err, res, body) {
console.log("body=",body);
console.log("res=",res);
})
});
I see no mistakes in your process of converting jpeg to base64. However, I would suggest a workaround to use a small image-to-base64 node package.
Also, there's a higher chance of something being wrong in the post request, maybe the upload service API is not accepting the base64 format, maybe the API key is not authorized. Please read their API docs carefully and do as it says & also console log the error code you are receiving.
After all, try something like this with Axios.
const image2base64 = require('image-to-base64');
image2base64("path/to/file.jpg") // you can also to use url
.then(
(response) => {
console.log(response); //cGF0aC90by9maWxlLmpwZw==
axios.post('http://example.com/in.php', base64, {
headers: {
"Content-Type": "multipart/form-data"
},
}).then((response) => {
console.log(response)
}).catch(function (error) {
console.log("Error in uploading.");
});
},
}
)
.catch(
(error) => {
console.log(error); //Exepection error....
}
)

Reading response from MongoDB after updating the database

I am trying to read/use the response from mongo db after I create a new record in the db. I am using Node JS, Angular 2/4 and Ionic 3. I am successfully able to post the request, however, I am stuck at reading the response(I get the response in JSON) Screenshot of the response in my console
Now in the js code, I am trying to get the value of FirstName. How do I access it ?
This is my ts code.
CreateProfile(){
this.Loader("Creating Account");
this.params={
FirstName:this.createDetails.get('firstName').value,
LastName:this.createDetails.get('lastName').value,
City:this.createDetails.get('city').value,
Dob:this.createDetails.get('myDate').value.formatted, //this.userDob, //this.formPersonal.get('dob').value,
State:this.createDetails.get('state').value,
EmailID:this.createAccount.get('email').value,
Phone:this.createDetails.get('phone').value,
Gender:this.createDetails.get('gender').value,
Address:this.createDetails.get('address').value,
PinCode:this.createDetails.get('pincode').value,
Password:this.createAccount.get('password').value
}
this.NewProfile.createProfile(this.params).then(res=>{
console.log(res);
})
}
I am printing my response on the console.log(res) which you can see on the attached image, I am tyring to access the values
I have tried res[0].FirstName
I have tried res.FirstName
I have got errors both times.
This is code from my router/provider file
public createProfile(options){
return new Promise((resolve, reject) => {
this.http.post(this.localUrl, options)
.map(res => res.json())
.subscribe(res => {
resolve(res);
}, (err) => {
reject(err);
});
});
}
I have removed all other codes irrelevant to this question. I am guessing this would be a very trivial issue but not able to figure out what I am missing here
I got the solution, I just had to use an array like this (below code)
this.NewProfile.createProfile(this.params).then(res=>{
console.log(res['FirstName']);
})
Didn't realize it was this straightforward

Node.js Streaming/Piping Error Handling (Change Response Status on Error)

I have millions of rows in my Cassandra db that I want to stream to the client in a zip file (don't want a potentially huge zip file in memory). I am using the stream() function from the Cassandra-Node driver, piping to a Transformer which extracts the one field from each row that I care about and appends a newline, and pipes to archive which pipes to the Express Response object. This seems to work fine but I can't figure out how to properly handle errors during streaming. I have to set the appropriate headers/status before streaming for the client, but if there is an error during the streaming, on the dbStream for example, I want to clean up all of the pipes and reset the response status to be something like 404. But If I try to reset the status after the headers are set and the streaming starts, I get Can't set headers after they are sent. I've looked all over and can't find how to properly handle errors in Node when piping/streaming to the Response object. How can the client tell if valid data was actually streamed if I can't send a proper response code on error? Can anyone help?
function streamNamesToWriteStream(query, res, options) {
return new Promise((resolve, reject) => {
let success = true;
const dbStream = db.client.stream(query);
const rowTransformer = new Transform({
objectMode: true,
transform(row, encoding, callback) {
try {
const vote = row.name + '\n';
callback(null, vote);
} catch (err) {
callback(null, err.message + '\n');
}
}
});
// Handle res events
res.on('error', (err) => {
logger.error(`res ${res} error`);
return reject(err);
});
dbStream.on('error', function(err) {
res.status(404).send() // Can't set headers after they are sent.
logger.debug(`dbStream error: ${err}`);
success = false;
//res.end();
//return reject(err);
});
res.writeHead(200, {
'Content-Type': 'application/zip',
'Content-disposition': 'attachment; filename=myFile.zip'
});
const archive = archiver.create('zip');
archive.on('error', function(err) { throw err; });
archive.on('end', function(err) {
logger.debug(`Archive done`);
//res.status(404).end()
});
archive.pipe(res, {
//end:false
});
archive.append(dbStream.pipe(rowTransformer), { name: 'file1.txt' });
archive.append(dbStream.pipe(rowTransformer), { name: 'file1.txt' });
archive.finalize();
});
}
Obviously it's too late to change the headers, so there's going to have to be application logic to detect a problem. Here's some ideas I have:
Write an unambiguous sentinel of some kind at the end of the stream when an error occurs. The consumer of the zip file will then need to look for that value to check for a problem.
Perhaps more simply, have the consumer execute a verification on the integrity of the zip archive. Presumably if the stream fails the zip will be corrupted.

Resources