Hi I am trying to insert data in the database using a POST Request but the data is not being inserted.
On further investigation I found that to upload form-data, busboy needs to be used for image upload in firebase functions but I am not able to find a solution for using busboy with post method.
Hence if someone can please help me resolve this issue.
Below is the code for reference.
app.js
const express = require('express')
//const router = true;
const router = new express.Router()
const userInfo = require('../models/userProfile')
const multer = require('multer');
var fs = require('fs');
var path = require('path');
var JSONStream = require('JSONStream');
const planCheck = require('../models/planDetails');
const login = require('../models/login_creditionals');
const {Storage} = require('#google-cloud/storage');
const {format} = require('util');
const busboy = require('busboy');
const storage = new Storage({
projectId: "biz-1",
keyFilename: "/Users/akm/pixNodes/functions/pixbiz-65a402.json"
});
const bucket = storage.bucket("gs://biz-1");
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 10 * 1024 * 1024
}
})
const uploadImageToStorage = (file) => {
return new Promise((resolve, reject) => {
if (!file) {
reject('No image file');
}
let newFileName = `${Date.now() + path.extname(file.originalname)}`;
let fileUpload = bucket.file(newFileName);
const blobStream = fileUpload.createWriteStream({
metadata: {
contentType: file.mimetype
}
});
blobStream.on('error', (error) => {
reject('Something is wrong! Unable to upload at the moment.');
});
blobStream.on('finish', () => {
// The public URL can be used to directly access the file via HTTP.
const url = format(`https://storage.googleapis.com/${bucket.name}/${fileUpload.name}`);
resolve(url);
});
blobStream.end(file.buffer);
});
}
router.post('/userprofile/check' ,upload.single('profile_pic'), async (req,res) => {
var reqFiles;
var reqFilesUrl;
reqFiles = req.file;
if(reqFiles) {
// const imagerUrl = await uploadImageToStorage(reqFiles)
reqFilesUrl = imagerUrl;
console.log(reqFilesUrl);
const notify = new userInfo({
userId: req.body.userId,
mobile_number : req.body.mobileNumber,
profile_pic: reqFilesUrl
})
try {
console.log('success insert data');
await notify.save((err,post) => {
if(err) {
console.log(err);
}
//console.log('data saved', post);
res.status(201).send(post);
});
// });
// res.status(201).send();
console.log('201');
} catch(e) {
//res.status(401);
return res.send(e);
}
I have created controller, routes and functions base api. What issue I am getting is how can I use Multer on function.
I have function like this
const { Users } = require('../models/user');
const { Company } = require('../models/company');
const { Jobs } = require('../models/job');
var mongoose = require('mongoose');
const multer = require('multer');
const FILE_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpeg',
'image/jpg': 'jpg'
};
const storage = multer.diskStorage({
destination: function (req, file, cb) {
const isValid = FILE_TYPE_MAP[file.mimetype];
let uploadError = new Error('invalid image type');
if (isValid) {
uploadError = null;
}
cb(uploadError, 'public/uploads');
},
filename: function (req, file, cb) {
const fileName = file.originalname.split(' ').join('-');
const extension = FILE_TYPE_MAP[file.mimetype];
cb(null, `${fileName}-${Date.now()}.${extension}`);
}
});
const uploadOptions = multer({ storage: storage });
const createJob = function async(req, res) {
const job = new Jobs({
jobTitle: req.body.jobTitle,
jobDescription: req.body.jobDescription,
jobImage: req.body.userType,
jobType: req.body.jobType,
jobNumberOfPeople: req.body.jobNumberOfPeople,
jobHireTime: req.body.jobHireTime,
jobMinPay: req.body.jobMinPay,
jobMaxPay: req.body.jobMaxPay,
jobday: req.body.jobday,
jobRecieveApplication: req.body.jobRecieveApplication,
jobSubmitResume: req.body.jobSubmitResume,
jobApplicationDeadline: req.body.jobApplicationDeadline,
jobCommunationSetting: req.body.jobCommunationSetting,
jobMessageSetting: req.body.jobMessageSetting,
companyID: req.body.companyID,
});
try {
const jobsave = await job.save();
res.status(200).json({ success: true, data: jobsave })
} catch (err) {
if (err.name === 'ValidationError') {
console.error(Object.values(err.errors).map(val => val.message))
return res.status(400).json({ success: false, message: Object.values(err.errors).map(val => val.message)[0] })
}
res.status(400).json({ success: false, message: err })
}
};
module.exports = { createJob };
and routes like this
const express = require('express');
const router = express.Router();
const userController = require('../controllers/user');
const jobController = require('../controllers/jobs');
router.post('/createJob', jobController.createJob);
module.exports = router;
now I need to add uploadOptions.single('jobImage') in function
I am doing like this const createJob =
const createJob = uploadOptions.single('jobImage'), async(req, res) => { };
Its showing this error on comma don't know why
Its working directly on router but I need to do In function
You can use this:
module.exports = {
createJob : [ uploadOptions.single('jobImage'), createJob ]
};
I have an API at https://dev-qaboomapi.azurewebsites.net/randmovie. I have a txt file that lists all movie IDs from https://themoviedb.org and one is selected at random and the information is presented at the API address above. What I can't work out is how to get it to check if the result is an english language movie and then try again if it isn't.
I have an If Else statement that checks the result is an english language movie but I can't work out if it isn't how to start the process again.
var appRouter = function (app) {
app.get("/randMovie", function (req, res) {
const fetchURL = require('fetch').fetchUrl;
const fs = require('fs');
const data = fs.readFileSync('./db/MovieIDs.txt') + '';
const splitData = data.split('\n');
const randomNumber = Math.floor(Math.random() * splitData.length);
const line = splitData.splice(randomNumber, 1);
const lineDATA = line.toString()
const api = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
var movieID = lineDATA
var URL = 'https://api.themoviedb.org/3/movie/' + movieID + '?api_key=' + api + "&append_to_response=videos"
fetchURL(URL, function(error, meta, body){
var movieString = body.toString()
var movieJSON = JSON.parse(movieString)
if(movieJSON.original_language == "en") {
res.status(200).send(movieJSON);
} else {
// Not sure what to put here
}
})
});
}
module.exports = appRouter;
I would like it to only return the details of the movie when it is:
if(movieJSON.original_language == "en")
and retry when it isn't.
Here is what you can try, but make sure that function does not run infinity if result is not in English.
var appRouter = function (app) {
app.get("/randMovie", function (req, res) {
retrieveData(req, res);
}
Definition of retrieveData
retrieveData(req, res){
const fetchURL = require('fetch').fetchUrl;
const fs = require('fs');
const data = fs.readFileSync('./db/MovieIDs.txt') + '';
const splitData = data.split('\n');
const randomNumber = Math.floor(Math.random() * splitData.length);
const line = splitData.splice(randomNumber, 1);
const lineDATA = line.toString()
const api = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
var movieID = lineDATA
var URL = 'https://api.themoviedb.org/3/movie/' + movieID + '?api_key=' + api + "&append_to_response=videos"
fetchURL(URL, function(error, meta, body){
var movieString = body.toString()
var movieJSON = JSON.parse(movieString)
if(movieJSON.original_language == "en") {
res.status(200).send(movieJSON);
} else {
// Not sure what to put here
retrieveData(req, res);
}
})
}
I had a task, after registering users in the application (registering through facebook) to keep facebook avatar in firebase storage, as facebook links have a limited period of work. I implemented the function I'll write below, but I get the following error
The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method
When I try to use a link to an image. Please tell me how it can be fixed?
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const gcs = require('#google-cloud/storage')({keyFilename: "service-account-credentials.json"});
const uuid = require('uuid');
const imageDownloader = require('../lib/Images/image-manager.js');
const path = require('path');
const timestamp = require('unix-timestamp');
module.exports = functions.https.onRequest((req, res) => {
const token = req.header('X-Auth-MyApp-Token');
const imageURL = req.body.imagePath;
const bucketName = functions.config().googlecloud.defaultbacketname;
const bucket = gcs.bucket(bucketName);
var userID = '';
const shortID = uuid.v1();
const filename = shortID + '.jpg';
var profileImagePath = '';
return admin.auth().verifyIdToken(token).then(decodedToken => {
userID = decodedToken.uid;
return imageDownloader.downloadImageToLocalDirectory(imageURL, filename)
}).then(localImagePath => {
profileImagePath = path.normalize(path.join('userImages', userID, 'profileImages', filename));
const uploadProm = bucket.upload(localImagePath, {
destination: profileImagePath,
uploadType: "media",
metadata: {
contentType: 'image/jpeg'
}
});
return uploadProm;
}).then(() => {
console.log('success uploaded');
const config = {
action: 'read',
expires: '03-01-2400',
contentType: 'image/jpeg'
};
const userRefPromise = admin.database().ref()
.child('users')
.child(userID)
.once('value');
const profileImageFile = bucket.file(profileImagePath);
return Promise.all([profileImageFile.getSignedUrl(config), userRefPromise])
}).then(results => {
const url = results[0][0];
const userModel = results[1].val();
const userCheckID = userModel['id'];
console.log("get url", url);
// save to database
const userImagesRef = admin.database().ref().child('userImages')
.child(userID)
.child('userProfileImages')
.push();
const timeStamp = timestamp.now();
console.log('timeStamp', timeStamp);
const imageModelID = userImagesRef.key;
const userImagesRefPromise = userImagesRef.update({
'path': url,
'id': imageModelID,
'fileName': filename,
'timeStamp': timeStamp
});
const userRef = admin.database().ref()
.child('users')
.child(userID)
.child('currentProfileImage');
const userRefPromise = userRef.update({
'path': url,
'id': imageModelID,
'fileName': filename,
'timeStamp': timeStamp
});
return Promise.all([userImagesRefPromise, userRefPromise]);
}).then(() => {
const successJSON = {};
successJSON["message"] = "Success operation";
return res.status(200).send(successJSON);
}).catch(error => {
console.log(error);
const errorJSON = {};
errorJSON["error"] = error;
return res.status(error.code).send(errorJSON);
});
});
I am working on a small project that works with generating pdf's in node and express, l am using the pdfkit npm module but to generate a pdf. l am also using the qr-image npm module to generate the QR code image but l am struggling to attach the generated the QR code to the pdf. This is the code that l am using to generate the QR code:
var file = "./"+certificationnumber+".png";
var qr_svg = qr.image(file, { type: 'png' });
qr_svg.pipe(require('fs').createWriteStream(file));
And this is how l am trying attache it to the pdf using pdfkit npm module:
doc.image(qr_svg.pipe(require('fs').createWriteStream(file)))
since every pdf has a unique QR code.
Thanks in advance
I exactly have the same problem where get the PDF in 64 bit encoded form and i have to attach qr image to it.
Below is the code snippet.
PDFDocument = require('pdfkit');
const base64 = require('base64-stream');
const doc = new PDFDocument();
doc.image('test.jpeg', {
fit: [250, 300],
align: 'center',
valign: 'center'
});
const finalString = pdf.response;
// contains the base64 string
//logic to append the qr image.
const stream = doc.pipe(base64.encode());
stream.on('data', chunk => finalString += chunk);
stream.on('end', () => {
// the stream is at its end, so push the resulting base64 string to the response
const backToPDF = new Buffer(finalString, 'base64');
read.writeFileSync('./Report.pdf', backToPDF);
});
doc.end();
Here is the solution I have come up with. Using pdf-lib, express and qrcode
const fs = require("fs");
const path = require("path");
const express = require("express");
const http = require("http");
const cors = require("cors");
const multer = require("multer");
const app = express();
const server = http.createServer(app);
const { PDFDocument } = require("pdf-lib");
const QRCode = require("qrcode");
const Joi = require("joi");
const { readFile, writeFile, unlink } = require("fs/promises");
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const dir = "public";
const subDirectory = "public/uploads";
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
fs.mkdirSync(subDirectory);
}
const generateQRCodeImage = async function (filePath, text, color) {
return new Promise((resolve, reject) => {
QRCode.toFile(
filePath,
text,
{
color,
},
function (err) {
if (err) return reject(err);
resolve();
}
);
});
};
const run = async ({
width,
height,
x,
y,
pathToImage,
pathToPDF,
pathToOutputPDF,
qrCodeText,
qrDarkColor = "#000",
qrLightColor = "#0000",
}) => {
await generateQRCodeImage(pathToImage, qrCodeText, {
dark: qrDarkColor,
light: qrLightColor,
});
const pdfDoc = await PDFDocument.load(await readFile(pathToPDF));
const img = await pdfDoc.embedPng(await readFile(pathToImage));
Array.from({ length: pdfDoc.getPageCount() }).forEach((_, index) => {
let imagePage = pdfDoc.getPage(index);
imagePage.drawImage(img, {
x,
y,
width,
height,
});
});
const pdfBytes = await pdfDoc.save();
await writeFile(pathToOutputPDF, pdfBytes);
};
const pdfFileFilter = function (req, file, callback) {
const ext = path.extname(file.originalname);
if (ext !== ".pdf") {
return callback("This extension is not supported");
}
callback(null, true);
};
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "public/uploads");
},
filename: function (req, file, cb) {
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
const filesToProcess = multer({ storage: storage, fileFilter: pdfFileFilter });
const schema = Joi.object({
width: Joi.string().regex(/^\d+$/).required(),
height: Joi.string().regex(/^\d+$/).required(),
x: Joi.string().regex(/^\d+$/).required(),
y: Joi.string().regex(/^\d+$/).required(),
qrCodeData: Joi.string().required(),
qrDarkColor: Joi.string(),
qrLightColor: Joi.string(),
});
app.post("/addQrToPdf", filesToProcess.array("file", 1), async (req, res) => {
const pathToImage = "public/uploads/" + Date.now() + "temp-qr.png";
const pathToOutputPDF = "public/uploads/" + Date.now() + "-output.pdf";
if (req.files) {
const [file] = req.files;
if (!file) {
res.send("No file detected on input");
}
const pathToPDF = file.path;
try {
const { width, height, x, y, qrCodeData, qrDarkColor, qrLightColor } =
await schema.validateAsync(req.body);
await run({
width: +width,
height: +height,
x: +x,
y: +y,
qrDarkColor,
qrLightColor,
qrCodeText: qrCodeData,
pathToImage,
pathToOutputPDF,
pathToPDF,
});
const pdfFile = await readFile(pathToOutputPDF);
res.contentType("application/pdf");
res.send(pdfFile);
await unlink(pathToImage);
await unlink(pathToPDF);
await unlink(pathToOutputPDF);
} catch (error) {
try {
await unlink(pathToPDF);
await unlink(pathToImage);
} catch (err) {
console.warn(err);
}
res.send(error);
}
}
});
server.listen(4000, () => console.log("listening on port *:4000"));
I had the same problem.
It looks like it is an async issue.
If you treat the generation of the QR code like a promise and then run the create pdf code, it works.
My code is below (using promise). It should also work using async await
const createPDF = (ticketID) => {
const doc = new pdf
doc.pipe(fs.createWriteStream(`${ticketID}.pdf`))
doc.text('Your Tickets').fontSize(25)
doc.image(`./qrCodes/${ticketID}.png`, {
fit: [250, 300],
align: 'center',
valign: 'center'
});
doc.end()
}
const createQRCode = (ticketID) => {
QR.toFile(`./qrCodes/${ticketID}.png`, String(ticket), {width: 250}).then(qr => {
createPDF(ticketID)
})
}
I use a version without writing to the disk, using the svg path output, extract the path from the qrcode data and render it into the pdf
let s = await toString('hallo2', {
type: 'svg'
})
// extract the 2nd path element
let path = Array.from(s.matchAll(/d="(.*?)"/gm))[1][1]
let doc = new PDFDocument({ size: 'A4' });
doc.scale(8)
.path(data)
.stroke()
doc.pipe(fs.createWriteStream('out2.pdf', {}));
doc.end()