Image to Base64 with NodeJS (Express) - javascript

I'm doing a test, and I need to convert an image to base64 to store in my DB
forget about DB, I just need the base64 as a string.
This is my form:
<form action="/cadastrado" method="POST">
<! -- other irrelevants inputs -->
<input type="file" name="input_file" id="input_file" onchange="converterParaBase64()" required><br>
<button type="submit" onclick="base64()">CADASTRAR</button>
</form>
This is my route after submit the form:
app.post("/cadastrado", (req, res) => {
const {input_nome, input_telefone, input_cpf, input_email, input_file} = req.body;
console.log(req);
return res.json({
nome: input_nome,
telefone: input_telefone,
cpf: input_cpf,
email: input_email,
// base64image: input_file.toBase64 (I need something like this)
});
});
I'm doing greate about using the strings inputs, like nome, telefone, cpf and email (variables in PT-BR)
But I can't say the same with input_file
When I console.log(req.body) i get this:
{
input_nome: '1',
input_telefone: '2',
input_cpf: '3',
input_email: '4',
input_file: 'levia.jpg'
}
I need to convert this levia.png image into base64 as a string.
How I can do it ?
UPDATE 1:
Seems like the image in json, is just the file name.
It is possible to convert in client-side and after send to server-side ?

Try this
var fs = require('fs');
app.post("/cadastrado", (req, res) => {
const {input_nome, input_telefone, input_cpf, input_email, input_file} = req.body;
console.log(req);
var bitmap = fs.readFileSync(input_file);
var base64File = new Buffer(bitmap).toString('base64');
return res.json({
nome: input_nome,
telefone: input_telefone,
cpf: input_cpf,
email: input_email,
base64image: base64File
});
});

so I figured out how to resolve my problem.
Kind of vicarious what I did. I don't know if in future this can result in a problem, so I want to share with you.
Basically I create a input and edit his value in client side. Of course, I don't want a big input with a Base64 code messing with my poor HTML, so I styled with display: none. This input is inside the form, and it is sent to my req.body.
Snippets
index.html page with form:
...
<input type="file" id="input_file" name="input_file" onchange="convBase64()" required />
...
script.js with some logic
...
document.getElementById('input_base64').value = `${stringBase64}`;
...
css to hide the input with encoded image:
#input_base64 {
display: none;
}
This invisible input is inside the form. When the form is submitted, the input value is sent to body of request.

Related

Node.js - Using input parsed from form to route to a specific URL

I am trying to allow a user to enter their name and have it added to the URL.
for example if the users input is John it redirects the user to "/profile/John"
So far I have tried to define a variable name from the parsed input from my html form.
html code;
<h4>Search for your profile by entering your name below.</h4>
<form class="" action="/" method="post">
<input type="text" name="name" placeholder="Enter your name">
<button type="submit" name="button">Search</button>
</form>
Node code;
app.get('/',function(req,res){
var name = String(req.body.name);
});
app.post("/profile/:" + name, (req,res)=>{
var data = {
age: 19,
job: 'Student',
hobbies: ['Fishing','Video games','Anime','Basketball']
};
res.render('profile',{name: req.params.name, data: data});
});
But I get this error;
^
app.get('/profile/:' + name, (req,res)=>{
^
ReferenceError: name is not defined
app.get('/',function(req,res){
// var name = String(req.body.name);
});
Above is not necessary part.
You should handle like below
app.post("/profile/:name", (req,res)=>{
var name = String(req.params.name)
var data = {
age: 19,
job: 'Student',
hobbies: ['Fishing','Video games','Anime','Basketball']
};
res.render('profile',{name: req.params.name, data: data});
});
You can check the details in this question
you need to put name inside the path quotes,
like this
app.get('/profile/:name',(req,res) =>{ }
the : after / indicates that the next value is dynamic
check out ExpressJS - URL Building

push array of strings to mongoDB with mongoose

I am not sure how to go about saving an array of strings from an input field to mongoDB with mongoose.
Ideally I would like to enter text several times in the same input field that creates an array. So I would end up having something like this.
title: "This is my Title"
actions: [ "walking", "smiling", "laughing"]
EJS File:
<form action="/blogs" method="POST">
<input type="text" placeholder="title" name="title" id="title" >
<input type="text" name="actions" id="actions" >
<button >submit</button>
</form>
blog.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const blogSchema = new Schema(
{
title: {
type: String,
required: true,
},
actions: [
{
type: String,
},
],
},
{ timestamps: true }
);
const Blog = mongoose.model("Blog", blogSchema);
module.exports = Blog;
app.js
app.post('/blogs', (req, res) => {
const blog = new Blog ({
title: req.body.title,
actions: req.body.tags,
});
blog.save()
.then((result) => {
res.redirect('/blogs')
})
.catch((erro) => {
console.log(erro)
})
})
Any guide on how to approach this? Right now my only solution is to create multiple input fields, but that is not correct.
If the actions tags are predefined and specific you can use html select multiple. That way actions property will be sent as an array of strings
<form action="/blogs" method="POST">
<input type="text" placeholder="title" name="title" id="title" >
<label for="actions">Actions:</label>
<select name="actions" id="actions" multiple>
<option value="walking">walking</option>
<option value="smiling">smiling</option>
<option value="laughing">laughing</option>
</select>
<button >submit</button>
</form>
And inside the controller you handle this way
// req.body.actions is already an array.
const blog = new Blog(req.body);
blog.save()
.then((result) => {
res.redirect('/blogs')
})
.catch((erro) => {
console.log(erro)
})
If, in any case, you want to use a text input to write the actions separated by space or comma, the actions property will be sent as a string. Then you can convert the string to array inside the controller.
// In case of multiple spaces, replace with single space.
// Then split string to array of strings
let actions = req.body.actions.replace(/ +/g, " ").split(" ")
const blog = new Blog ({
title: req.body.title,
actions
});
// rest of code
Whatever you choose to do, the actions will be stored as array of strings in the database.
Possibly you are sending an array as a string to the mongo. You can check this by checking the type of req.body.tags like so:
console.log(typeof req.body.tags)
If this returns a String, make sure you send the content as JSON to the database.

Dynamic sendgrid templates being sent as plain text

I'm sending email through sendgrid, but when I receive the email, the email is in plain text format, and I would like to send it in html format.
The variable data is the data I pass to sgMail.send.
module.exports = {
data: {
to: '',
from: '',
subject: '',
text: '',
templateId: '',
dynamic_template_data: {
value_precip: undefined,
value_humidity: undefined,
value_windSpeed: undefined,
value_condition: undefined,
value_activiti: undefined
}
},
set: function(to, from, subject, text, templateId, params) {
this.data.to = to
this.data.from = from
this.data.subject = subject
this.data.text = text
this.data.templateId = templateId,
this.data.dynamic_template_data.value_precipitation = params.value_precipitation
this.data.dynamic_template_data.value_humidity = params.value_humidity
this.data.dynamic_template_data.value_windSpeed = params.value_windy
this.data.dynamic_template_data.value_condition = params.value_condition
this.data.dynamic_template_data.value_activiti = params.value_activiti
},
send: function() {
try {
sgMail.send(this.data)
} catch (error) {
console.log(error)
}
}
}
I don't know what may be causing this problem, if anyone can help me I would be grateful!
It's simple, just remove the text.
As mentioned by a contributor of SendGrid. Read more
Given that dynamic templates contain both HTML and plain text content, text should not be passed when using a dynamic template.
It looks like SendGrid uses html attribute to decide if the content type should be html even though they ignore the content. So, just include that attribute in the payload. Seems weird, but it worked for me.
P.S.: I didn't try it with JavaScript, I'm using Python.

retrieve array in jquery $.post

I have a problem browsing elements of my forms and posting them as "JSON". I manage to recover everything except some elements like the names of people for example, which are dynamic.
I actually choose a number of names to give, and I would like to get what I have in my array of name.
here is my code :
<script>
parseInt($('#id').html());
console.log(parseInt($('#id').html()));
var handler = StripeCheckout.configure({
key: 'pk_test_nWBzhwnk9WLgDk5EHjr3JTuZ',
image: 'http://localhost:8000/images/default.png',
color: 'white',
locale: 'auto',
token: function(token) {
// You can access the token ID with `token.id`.
// Get the token ID to your server-side code for use.
var myData = {
token: token.id,
email: token.email,
amount: Math.round($("#result").text()),
description: '',
currency: 'eur',
event: parseInt($('#id').html()),
nb_tickets : $('#nb_ticket').text(),
name: [],
};
/*
Make an AJAX post request using JQuery,
change the first parameter to your charge script
*/
$('body').Wload({text:'Paiement en cours'});
console.log(myData);
$.post("/checkout/"+parseInt($('#id').html()), myData,
function(data) {
// if you get some results back update results
$("#myForm").hide();
// for demonstration purposes, loop through everything in myData
})
.done(function () {
$('#element_to_pop_up').bPopup({
modalClose: false,
});
$('body').Wload('hide', {time: 0});
})
.fail(function() {
// if things fail, tell us
$(".results").html("I'm sorry something went wrong");
})
}
});
depending on the number of tickets I choose I can have several names.
in my form the ID of the names is as follows if I choose 2 tickets:
<input type="text" id="commande_achats_0_name" name="commande[achats][0][name]" required="required" class="form-control" placeholder="Name">
and :
<input type="text" id="commande_achats_1_name" name="commande[achats][1][name]" required="required" class="form-control" placeholder="Name">
I need to recover everything in commande_achats_0_name and commande_achats_1_name according to the number of tickets chosen..
I'm stuck on it .. if anyone could help me please
Thank you

SendGrid Content Templating with Nodejs

How do I template SendGrid's content with Nodejs?
I am trying to send emails from contact form in an application using SendGrid. I have a Google Cloud Function that I am calling via an HTTP post. I am able to pass in the form data as a JSON object to my Google Cloud Function, and display a raw JSON object in my email content, but when I try to template my SendGrid content, the JSON object's properties keep coming back as undefined. How do I display my different formData properties within my SendGrid email content?
Here is the code:
const functions = require('firebase-functions');
const sg = require('sendgrid')(
process.env.SENDGRID_API_KEY || '<my-api-key-placed-here>'
);
exports.contactMail = functions.https.onRequest((req, res) => {
contactMail(req.body);
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.send("Mail Successfully Sent!");
})
function contactMail(formData) {
const mailRequest = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: {
personalizations: [{
to: [{ email: 'my.email#gmail.com' }],
subject: 'Contact Us Form Submitted'
}],
from: { email: 'noreply#email-app.firebaseapp.com' },
content: [{
type: 'text/plain',
value: `
You have received a contact us form submission. Here is the data:
Name: ${formData.userFirstName} ${formData.userLastName}
Email: ${formData.userEmail}
Subject: ${formData.formSubject}
Message: ${formData.formMessage}
`
}]
}
});
sg.API(mailRequest, function (error, response) {
if (error) {
console.log('Mail not sent; see error message below.');
} else {
console.log('Mail sent successfully!');
}
console.log(response);
});
}
This displays undefined for each template expression.
However if my content section is set to this:
content: [{
type: 'text/plain',
value: formData
}]
Then the email content is displayed as a raw JSON object.
How do I clean up my SendGrid email content and display my JSON data in a formatted, cleaner way?
The problem was my req.body was a text string, not a JSON object.
Using const formData = JSON.parse(req.body); and then passing this variable to contactMail will properly display the JSON object's properties in an ES6 template literal.

Categories