Send blob-data along with a string to backend - node.js

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.

Related

I want to preserve backend data on reload

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.

How to send a get request in GraphQL, to get an image from the project's folder?

I am new to GraphQL an do not fully understand its possibilities. However I need to convert my REST request to GraphQL request and here is my question, how can I implement following code in GraphQL?
router.get('/image/:id', (req, res) => {
const path = 'images/' + req.params.id + '.jpg';
return res.sendFile(path, { root: 'src/' })
})
For my other requests I am working with mongodb database, and I could convert my REST requests to Graphql request, but for this piece of code, I have no idea how to implement that.
Thank you in advance
This isn't something you can recreate with GraphQL. It's a standard for data querying and retrieval and it expects that the response from the GraphQL endpoint be a valid JSON.
The best thing to do is to keep your existing endpoint and use it for fetching images when necessary.
If you're dead set on returning the data through GraphQL, you can also try base64 encoding it so you can convert the binary data into a string that you can convert back into a Buffer on the client.
The resolver for that would look something like this:
import { promises as fs } from "fs";
const getImage = async (_, { id }) => {
const fileBuffer = await fs.readFile("images/" + id + ".jpg");
return fileBuffer.toString("base64");
}

Next JS, how to send files uploaded to the front end to the back end?

I have a Next application that is a job board. I need to allow the users to upload two files, a resume, and a cover letter. After this, I need to take the files and other information the users provided, then send that information in an email to the employer I have on file for that job posting. The problem I am having is that even though I can get the files and information in a formData object when I send it to my API, I am not able to get the files to use.
This is the method I am using to get the information from the front end and put it into a formData object.
const handleSubmit = async (e) => {
e.preventDefault();
let form = new FormData(e.target);
form.append('resume', resume);
form.append('coverLetter', coverLetter);
const formData = Object.fromEntries(form.entries());
console.log(formData);
try {
const res = await fetch('http://localhost:3000/api/applyForJob', {
body: JSON.stringify(formData),
method: 'POST',
});
const result = await res.json();
console.log(result);
} catch (error) {
console.log('Error with sending the POST request');
console.log('Here is the trace');
console.error(error);
}
};
Here is the formData object in the console:
You can clearly see that all the information is there, including the files. Here is the code for the API route:
export default async function handler(req, res) {
console.log(typeof req.body);
console.log(req.body);
console.log(req.candidateEmail);
console.log(req.resume);
}
I should be able to access everything in the request. But here is what the console logs print:
string
{"candidateFirstName":"Lawrence","candidateLastName":"Mueller","candidateEmail":"lawrencemueller18#gmail.com","candidatePhone":"16266786830","candidateResume":{},"candidateCoverLetter":{},"resume":{},"coverLetter":{}}
undefined
[Function (anonymous)]
The resume and cover letter fields, show {}, so blank. All I need to do is access the files from the front end, just send an email using them. I do not care about storing them at all. Thank you in advance for any help I am given.

How to send a file when getting it with request?

I am making a request with a mandatory request and I need to send the response to the immediate user. I mean, I need to send the data just when I receive it.
I want request to make the request and as it obtains the data, it will send it to the user in real time.
I have the following code and all I can do in this way is save the file and then send it, which does not work at all well, because it takes even longer to send the file
const def = (req,res)=> {
const request = request.get("url")
const getFile = fs.createWriteStream("path")
request.on("error", ()=> {
res.send("error")
})
request.pipe(getFile)
getFile.on("finish", ()=>{
const sendFile = fs.createReadStream("path")
sendFile.on("data", (chunk)=>{
res.send(chunk)
})
sendFile.on("finish", ()=> {
res.end()
})
})
}
This works but has several problems.
I need to save the file
Until it is downloaded to the server, it cannot be sent
It is much slower than sending it in real time
I need something maybe like the following (I know that this does not exist in such a way but I try to give an idea)
request.on("data", (chunk)=>{
res.send(chunk)
})
request.on("finish", ()=> res.end())
//or
getFile.on("data", (chunk)=>{
res.send(chunk)
})
getFile.on("finish", () => res.end())
Please help me
Just pipe the response directly to the client:
const def = (req, res) => {
request
.get("url")
.on("error", () => {
res.send("error")
})
.pipe(res)
}
Official documentation.

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

Resources