I want to preserve backend data on reload - node.js

I have created an app that has a cart that sends data to the backend, now when I restore I want to preserve the data and display the same data as before.
I have used the PUT method instead of POST and when I send and get data from Firebase, data is preserved on reload and the data from the database is visible, but if I use my own backend in Node.js, I am not able to get the data on reload. This is where I am fetching data from the backend.
export const fetchCartData=()=>{
return async(dispatch)=>{
const getData= async() =>{
const response = await fetch('https://localhost:5000/');
if(!response.ok){
throw new Error('Something went wrong');
}
const info=await response.json();
return info;
};
try{
const data= await getData();
console.log("Here is data from Firebase", data);
dispatch(order_action.replaceCart({
items:data.items || [],
totalQuantity:data.totalQuantity || 0
}));
}catch(error){
dispatch(show_action.showNotification({
status:"failed",
title:"Error...",
message:"Some error occurred."
}));
}
}
}
Tha backend Code is:
const express=require("express");
const bodyParser=require('body-parser');
const cors=require('cors');
const app=express();
app.use(cors());
app.use(bodyParser.json());
app.put("/",function (req,res) {
const data={
items:req.body.items,
totalQuantity:req.body.totalQuantity
}
console.log(data);
console.log("END");
res.send({data});
})
app.get("/",function (req,res) {
console.log(req.body);
const data={
items:req.body.items,
totalQuantity:req.body.totalQuantity
}
res.send({data})
})
app.listen(5000,function () {
console.log("Running on 5000");
})

You can use localStorage on the browser i.e at the client-side. Whenever there is any change in the cart do these steps:
Send data to the backend API using the PUT method and store it in DB or cache(based on the website and users you are dealing with).
Once you get the response from API, update your localStorage data.
localStorage.set('cart', JSON.stringify(dataFromAPI));
Now, on every reload you will always be getting the last updated cart data.
when I send and get data from Firebase, data is preserved on reload
and the data from the database is visible
Just for your knowledge, firebase is a database and when you save data, it is persistent. Now, on reload you must be calling the firebase DB to get the data back that's why you see the data on the client otherwise it is impossible to get data without caching or saving it locally.

You can store/contain the data in a JSON file and reuse the data.
If the data is a stream of data, then you do only need some latest records; you can perform some JavaScript array operations to perform a First-In-First-Out operations by containing up to like 50 or 100 objects/records in the JSON file, so you can later retrieve/reuse.
const fs = require("fs");
const path = require("path");
const data = fs.readFileSync(path.resolve(__dirname,"filename.json");
const data = JSON.parse(data);
data.contentArray.push(req.body); //or any other data
const data = JSON.stringify(data);
fs.writeFileSync(path.resolve(__dirname,"filename.json",data,"utf-8");
/*
filename.json sample
{
"contentArray":[
{
"key":"value"
},
{
"key":"value"
}
]
}
*/
You can find ways to literally store/contain the data in a '.json' file or '.csv' file. I would recommend storing the data in a JSON file, which is way easier.

Related

Send blob-data along with a string to backend

I´ve got a weird problem.
Using Node, React, Express, MongoDB -> MERN Stack.
So my page generates a PDF file which then gets send to the backend (as blob data) and is being stored on there.
The problem I have, now I need to send a payment ID along with that blob data to save the order in the data base. I need both in one post request, to make it as smooth as possible:
await axios
.post(process.env.REACT_APP_SERVER_API + '/payment/cash', {
blobData,
paymentId
})
.then(async (res) => ...
like so.
Before, when I just sent the blob data, I could simply access the data in the backend by writing:
exports.createCashOrder = async (req, res) => {
const { filename } = req.file; // THIS RIGHT HERE
const fileHash = await genFileHash(filename);
try {
await saveOrder(filename, fileHash, "cash", paymentId);
//await sendOrderCreatedEmail(req.body, fileHash);
//await sendOrderReceivedConfirmEmail(req.body, fileHash);
res.send({ filename: filename });
}
But that doesn't work anymore. I dont have access to that file object anymore when sending that request object.
Neither by trying
req.body.blobData
req.body.blobData.file
req.file
Any idea how to achieve that, except from making two seperate post requests?
Glad for any help, cheers!
Send the data as a form
await axios
.postForm(process.env.REACT_APP_SERVER_API + '/payment/cash', {
blobData,
paymentId
})
.then(async (res) => ...
And then use multer middleware to handle the form in express.

Update Frontend after using Delete Route in Express.js

I have created a delete route in express.js that looks like the following:
router.delete("/notes/:id", (req, res) => {
console.log("delete route called")
const noteToRemove = findById(req.params.id, notes);
const result = notes.filter(note => note !== noteToRemove)
console.log(result);
fs.writeFileSync(
path.join(__dirname, '../../db/db.json'),
JSON.stringify({ notes: result }, null, 2)
);
)}
findById is a function I have declared in another file to locate an item in my database db/db.json that locates an item based on an ID I created earlier.
The issue here is that this code will remove an item from the database, but I want the frontend to show the updated list from the database. How does one reload the frontend to see the updated changes in the database?
Two things:
You will need to include a response in your server side method to let the client know that the resource was deleted. You should also add responses with error codes in cases something goes wrong, but for simplicity here we only address the nominal case.
router.delete("/notes/:id", (req, res) => {
console.log("delete route called")
const noteToRemove = findById(req.params.id, notes);
const result = notes.filter(note => note !== noteToRemove)
console.log(result);
fs.writeFileSync(
path.join(__dirname, '../../db/db.json'),
JSON.stringify({ notes: result }, null, 2)
);
res.end(); // respond to the client to let them know we are finished
)}
On the front-end you will need to react to this response and reload the resources. This highly depends on how your front end is structured and how it gets data from the server. As a hack, for now, you can just call location.reload(), which will do the trick in the vast majority of cases -- but isn't very elegant of course nowadays where you could refetch and render just parts of the data and page.

nodejs: Retrieving base64 Images from Mongodb using Postman

Looking for help on Uploading and Retrieving Images from MongoDb using multer.
My front end is ReactNative.(Not sure if this is needed but just to be sure.)
Multer
Problem: After looking and following tutorials i'm able to encode my path to base64 and upload it to my DB but now i'm confused how to retrieve the file from my DB. I saw some tutorials about decoding it from base64 but I don't quite understand how do I go about retrieving an image and displaying it in postman. (I tried looking but haven't found anything that gives me an answer. I'm sorry if this is a duplicated question. If you could point me in a direction or give me some advice I would be really greatful.)
**POST**
route.post("/sad", upload.single("image"), (req, res, next) => {
console.log(req.file);
const img = fs.readFileSync(req.file.path);
const img_enc = img.toString('base64');
const obj = {
usrImage: {
data: new Buffer.from(img_enc, 'base64'),
contentType: "image/jpg",
},
};
console.log(obj);
const newAccout = new account(obj);
newAccout.save();
});
**RETRIEVE**
route.get('/sad',(req,res)=>{
img.find({}).then((img)=>{
res.json(img)
//How do decode my buffer to show an image in Postman?
})
}
)
I am trying to create a userprofile where a username,password and image is saved. If you can help save an Image and then retrieve it from my accounts collection.
Hey I would advise that you start using a 3rd party for file upload like cloudinary very good way of managing files i.e images or video...
I am not that well of with multer but I can give a quick code example using Formidable does the same work as multer
Before you can start you'd need to make an account on cloudinary.com(don't worry its free)
Code below is how you could handle file upload
const Formidable = require("formidable"); //Meant for body parsing
const cloudinary = require("cloudinary").v2; // file uploader
//This below is your connection/configuration to get access to your cloudinary account so cloud_name, api_key and api_secret you'll get in your home dashboard(Cloudinary)
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET,
});
router.post('/api/file-upload', (req, res)=>{
const form = new Formidable.InconmingForm();
form.parse(req, (error, fields, files)=>{
const {file} = files
cloudinary.uploader.upload(file.path, {folder:"/"}, (err, res)=>{
const file_url = res.secure_url //This would be the url for your file given back by cloudinary
})
})
})
This script should upload your file and the file_url will be having the url of the file that you upload having ssl then after that you can now continue saving to mongoDB
Cloudinary docs for NodeJS
https://cloudinary.com/documentation/node_integration
Nice clear and understandable docs
Shameless plug
If you get lost you can check this video out on YouTube that I made handling file upload with cloudinary then save url given back to mongoDB
https://youtu.be/mlu-tbr2uUk
First call api find one
you will need fs module to complete following query
const fs = require('fs');
let data = await db.user.findOne({
where: {
id = req.body.id
}
})
// _________________ base 64 string data from findone query data
// |
let buff = new Buffer(data.image, 'base64');
let name = name.jpeg
let path = `tmp/${name}`; // <--- destination and file name you want to give to your file
fs.writeFileSync(path, buff);// < --this will write file to given path
fs.readFile(path, function (err, content) {// <------to send file in postman response
if (err) {
res.writeHead(400)
console.log(err);
res.end("No such image");
} else {
//specify the content type in the response will be an image
res.writeHead(200);
res.end(content);
}
});
fs.unlink(path, (err) => { // <-----to delete file from tmp directory
if (err) {
console.log(err)
}
})
Try this and switch to preview tab in postman.
I haven't tried it but maybe it helps.
route.get('/sad',(req,res)=>{
img.find({}).then((img)=>{
res.setHeader('contentType','image/jpg').send(img)
})
})

Requesting infromation from a API through Node.js

I hope you could please help me out, I'm running Node.js and trying to get a the city name from a API and it keeps showing an error
saying it Cannot read property city_name of undefined.
It gets stuck on this line in the code:
const cityName = weatherData.data.city_name;
Any clue why its doing that? Please
// Creating the server of the weather app
const express = require('express');
const app = express();
const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');
const https = require('https');
app.get('/', (req, res) => {
const weatherPath = "https://api.weatherbit.io/v2.0/current?key=41c0f84d717a4764a26d144aa33a9443&city=melbourne,Australia"
// Calling the weather app
https.get(weatherPath, (response) => {
console.log(response.statusCode);
// Getting the data from the weather app
response.on('data', (d) => {
//console.log(d);
// Converting the buffer data from the weather app
console.log(decoder.write(d));
const weatherData = decoder.write(d);
const cityName = weatherData.data.city_name;
console.log(cityName);
});
});
res.send("The server is up and running on the web");
});
app.listen(3000, () =>
{
console.log('Server is running on port 3000');
});
Your data is a string and hence doesn't have those properties. You would need to JSON.parse it first.
But there is another issue, your code will break as soon as more data is returned, because you listen only for a single chunk of data. You have to add up all chunks (add to the existing chunks on every data event) and process the full data on the end event.
But in general the https.get method is very bare-bones, it will be a lot simpler to use a package like node-fetch:
// Creating the server of the weather app
const express = require('express');
const app = express();
const fetch = require('node-fetch')
app.get('/', (req, res) => {
const weatherPath = "https://api.weatherbit.io/v2.0/current?key=41c0f84d717a4764a26d144aa33a9443&city=melbourne,Australia"
// Calling the weather app
fetch(weatherPath)
.then(response => response.json())
.then(weatherData => {
// Getting the data from the weather app
const cityName = weatherData.data[0].city_name;
console.log(cityName);
}).catch(e => {
console.error('An error occured!', e);
});
res.send("The server is up and running on the web");
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Additional information
To address your comment:
I converted the data into a string though in the command line it looked like a JSON.
The term "JSON" is often used in a confusing way. Technically JSON (JavaScript Object Notation) is a serialization format, a string representation of an object or other basic JavaScript datatype (with limitations). The concept of a "live" object exists only in memory inside your script. So, the API is always sending you a string of characters. This string "is" JSON, i.e. uses JSON as method of representing structured data that, when parsed (!), can be turned back into a JavaScript object (in memory). So you are right that it looked like JSON since it is, but it's still a string at that point.
It's like sending you a blueprint (2D representation - JSON string) of a house (3D object - the original object). (You obviously can't send a house in a letter so people are sending blueprints (JSON) instead.) It looks like a house, because it is representing one, but you can't yet open its door (access a property) or something. At that point it's still just something printed on a piece of paper (a string) that people recognize as a blueprint (it is valid JSON). You have to first build an actual house (parse the JSON back into an object) from the blueprint.
(Of course this isn't made any better by using a variable name like json to represent the data parsed from JSON like it sometimes happens.)
I tried to hit the API and the response :
{"data":[{"rh":73,"pod":"n","lon":144.96332,"pres":1025.6,"timezone":"Australia\/Melbourne","ob_time":"2020-07-09 09:05","country_code":"AU","clouds":50,"ts":1594285500,"solar_rad":0,"state_code":"07","city_name":"Melbourne","wind_spd":1,"wind_cdir_full":"north-northwest","wind_cdir":"NNW","slp":1026.3,"vis":5,"h_angle":-90,"sunset":"07:16","dni":0,"dewpt":8.2,"snow":0,"uv":0,"precip":0,"wind_dir":348,"sunrise":"21:34","ghi":0,"dhi":0,"aqi":61,"lat":-37.814,"weather":{"icon":"c02n","code":"802","description":"Scattered clouds"},"datetime":"2020-07-09:09","temp":12.8,"station":"E5657","elev_angle":-20.02,"app_temp":12.8}],"count":1}
Edit :
i dont try your code in application before, i try by browser
This is mycode
// Calling the weather app
https.get(weatherPath, (response) => {
response.setEncoding('utf8')
let chunks = []
// Getting the data from the weather app
response.on('data', (d) => {
chunks.push(d);
});
response.on('end', () => {
let data = JSON.parse(chunks.join(''))
console.log(data.data[0].city_name)
});
});
weather.data is an array, so when you try access weather.data.city_name will be undefined. You must access weather.data[0].city_name.
I have solved using advance node module used popularly called axios
Have a look at Code,
// Creating the server of the weather app
const express = require('express');
const app = express();
const axios = require('axios');
app.get('/', (req, res) =>
{
//In production we do not need this
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
const weatherPath = "https://api.weatherbit.io/v2.0/current?key=41c0f84d717a4764a26d144aa33a9443&city=melbourne,Australia";
axios.get(weatherPath)
.then(function (response)
{
// handle success
let cityName = response.data.data[0].city_name;
console.log(cityName);
})
.catch(function (error)
{
// handle error
console.log(error);
})
.finally(function ()
{
// always executed
});
res.send("The server is up and running on the web");
});
app.listen(3000, () =>
{
console.log('Server is running on port 3000');
});

What does this JSON response mean?

I am following a MEVN stack tutorial: https://appdividend.com/2018/11/21/mevn-stack-tutorial-with-example-from-scratch/#8_Setup_and_connect_MongoDB_database
In section 10 he shows how to create routes for adding, deleting, updating and reading data in a mongoDB database using mongoose.
This is part of that code:
// post.model.js
const express = require('express');
const postRoutes = express.Router();
// Require Post model in our routes module
let Post = require('./post.model');
// Defined store route
postRoutes.route('/add').post(function (req, res) {
let post = new Post(req.body);
post.save()
.then(() => {
res.status(200).json({'business': 'business in added successfully'});
})
.catch(() => {
res.status(400).send("unable to save to database");
});
});
Is there a specific reason he has put {'business': 'business in added successfully'} in the JSON for the 200 response? or can that just be anything? Also i'm not entirely sure what i would put in it for my specific scenario where i am trying to add, delete, update and read data about users in a 'users' collection.
It can be anything, just to information that received request is successful and created the records. He added some response to that request.

Resources