Forward POST request from express to mail - node.js

I generate a pdf on client side with jspdf and send it to an express server with formData
var blob = pdf.output('blob');
var formData = new FormData();
formData.append('pdf', blob);
$.ajax('http://localhost:8080/test/first',
{
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){console.log(data)},
error: function(data){console.log(data)}
});
The request arrives on the server, which I can see in my console, however, I don't see the body. I am new to node and express, so I am not really clear how to test this. However, the file doesn't need to be saved on server anyway, but just forwarded to a certain email. So I thought maybe, if I manage to forward, I can actually see my pdf as an attachement. Is there a simple way to forward this formData? I already have a sceleton for it, but I am stuck how to proceed.
exports.sendForm = async (body) => {
try {
console.log(body);
// todo send form data to email: test#gmail.com
return;
} catch (err) {
return next(err);
}
};

You can use multer to handle file upload, then you can access the file in route handler from req.file
Then you can send the file as a mail attachment using nodemailer
Multer - https://www.npmjs.com/package/multer
Nodemailer example with attachment - https://nodemailer.com/message/attachments

Related

ERR_HTTP_HEADERS_SENT caused by response to POST request after refresh node.js Express. res.send inside fs.watch callback

On my webpage user can enter text and press send. this causes the server to append the message to a json object stored in a file. when this file is altered it then sends the new json to the client.
app.post("/recieve",function(req,res){
watcher = fs.watch(__dirname+"/msgs/msg.json", (eventName, filename) => {
watcher.close();
fs.readFile(__dirname+"/msgs/msg.json", (err,data) => {
return res.send(data);
});
});
})
here is the client side
async function recieveMSG(){
$.ajax({
url: "recieve",
type: "POST",
contentType: "text; charset=utf-8"
}).done(function(data){
$("#msgbox").html("<br>"+data+"<br>");
recieveMSG();
});
}
recieveMSG();
As shown in the code above, the client sends a POST request to the server. Next after the json file is changed the server responds to the POST request with the json. I know this may be the completely wrong way to do it, but I want to know why res.send(data) is being called twice on the same res object.
It seems after the first refresh the recieve POST request just doesnot do anything
app.post("/recieve",async function(req,res){
try{
watcher.close();
}
catch(e){
console.log("WatcherUndefined --first execution");
}
watcher = fs.watch(__dirname+"/msgs/msg.json", (eventName, filename) => {
watcher.close();
fs.readFile(__dirname+"/msgs/msg.json", (err,data) => {
return res.send(data);
});
});
})
The problem was that the watcher wasn't getting closed after the client refreshed/disconnected. After the client refreshed the res object generated by their stale request is unusable. I believe that the watcher's callback was never redefined with the new res object (after refresh). I do not know if my assumption is correct, and would like to hear other's thoughts on this as I am new to nodejs.

Telegram Bot - How to upload local files with absolute/ dynamic URL

I'm trying to send photos through telegram bot using 'sendPhoto' method with relative url (Image at file level). I'm not using any library, here is my call function:
let axiosImage = async (chatId, caption, res) => {
try {
await axios.post(`${TELEGRAM_API}/sendPhoto`,
{
headers:{'Content-Type': 'multipart/form-data'}
},{
body: {
'chat_id': chatId,
'caption': caption,
'photo': './image.jpeg'
}
})
return res.send()
} catch (e) {
console.log('\nSTATUS RESPONSE: ' + e.response.status)
console.log('\nMESSAGE RESPONSE: ' + e.response.statusText)
}}
but I'm getting this message back: {"ok":false,"error_code":400,"description":"Bad Request: there is no photo in the request"}
I tried with a web url and it sends normally.
What could I be missing? Do I have to upload the local images in some repository?
I had a similar issue recently, I managed to solve the problem using form-data npm package and built-in fs module.
const FormData = require('form-data');
const fs = require('fs');
const axiosImage = async(chatId, caption, res) => {
try {
const formData = new FormData();
formData.append('chat_id', chatId);
formData.append('photo', fs.createReadStream('./image.jpeg'));
formData.append('caption', caption);
const response = await axios.post(`${TELEGRAM_API}/sendPhoto`, formData, {
headers: formData.getHeaders(),
});
return res.send();
} catch (err) {
console.log(err);
}
}
From the Telegram api docs
If the file is already stored somewhere on the Telegram servers, you don't need to reupload it: each file object has a file_id field, simply pass this file_id as a parameter instead of uploading. There are no limits for files sent this way.
Provide Telegram with an HTTP URL for the file to be sent. Telegram will download and send the file. 5 MB max size for photos and 20 MB max for other types of content.
Post the file using multipart/form-data in the usual way that files are uploaded via the browser. 10 MB max size for photos, 50 MB for other files.
What you want to send is a file via file upload (3.). This is the answer to what you are trying to achieve:
https://stackoverflow.com/a/59177066/4668136

Send multiple files from one API to another with NodeJS , multer and Axios

I have an API in one nodejs project as below which receive multiple attachment from UI:
const upload = multer()
router.post('/upload', upload.array("attachments"),controller.getSomething);
getSomething is supposed to call another POST API using Axios only, which is in another NodeJs project which accept these attachments and process it. It as well accept multiple files via multer.
I am unsure how could i send multiple files as a request from one Nodejs project to another at once. could you please favour.
I had to set formdata as below:
const formData=new FormData();
for(let file of req.files){
formData.append("attachments",file.buffer,file.originalname);
}
And passed the formdata to other api via axios.
You can do the following steps:
When you upload the temporary files (coming from UI), save them in the temporary folder.
Pass all the files names to the POST API using Axios.
In the post API, read all the files from the temporary folder and stream them to the destination.
controller.getSomething = (req, res, next) => {
// get the file names
const fileNames = req.files.map(filename => filename);
// now post this filenames to the
axios.post('/pathname', {fileNames})
// or, you can use get request
}
Reading files in the post Request:
var promises= ['file1.css', 'file2.css'].map(function(_path){
return new Promise(function(_path, resolve, reject){
fs.readFile(_path, 'utf8', function(err, data){
if(err){
console.log(err);
resolve(""); //following the same code flow
}else{
resolve(data);
}
});
}.bind(this, _path));
});
Promise.all(promises).then(function(results){
//Put your callback logic here
response.writeHead(200, {"Content-Type": "text/css"});
results.forEach(function(content){response.write(content)});
response.end();
});
#copied from this link. You should check the different answers that can help you.

Image is not uploading using request.post getting undefined value

const formData = req.file('image')
const options = {
url: 'myurl'',
method: 'POST',
formData : formData
}
request.post(options, async function(err,result,body){
if(err)
{
res.json({
success: false,
message: "There are some error occured in file upload"
});
}
else
{
res.json({success: true});
}
});
I am trying to upload an image using request.post but it does not allow me to upload the image please guide how can I fix it
Please guide
Edit1:
I am using ejs as frontend.
Trying to send that uploaded image from one server(example1.com) to other server(example2.com).
Server1(example1.com) is powered with sails.js.
Thanks
Use enctype='multipart/form-data' in your ejs form.
Since you are sending that image from one backend(example1.com) to other backend(example2.com) using microservervice, first save that image in your first backend(example1.com)
Then pass that image path(example1.com/images/img1.jpg) to the post request. For example
postdata = {
imageurl: 'example1.com/images/img1.jpg',
imagesize: '1200',
}
Only example1.com can be able to access your local image path(For example: c://temp/img1.jpg). So you should upload that image in your server 1(example1.com)
Alternatively convert the image to blob type and send. This way you don't need to save the image in server1(example1.com).

NodeJS: Issue with handling file uploading

I did not know what to write as the title, as I am having a very strange issue. What I am trying to do is upload and save *.html files on server. Following is the code structure:
Jade Template (Form):
#template-uploader
form(enctype='multipart/form-data')
input(name='file', type='file')
input#upload-template(type='button', value='Upload')
JS (Form Handle):
//Upload Btn Click Event Handler
$('#upload-template').on('click', function(){
event.stopPropagation();
event.preventDefault();
uploadFiles();
});
// Upload the files using AJAX
function uploadFiles()
{
var formData = $('input[type=file]')[0].files;
$.ajax({
url: 'template/upload',
type: 'POST',
xhr: function() { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){
// For handling the progress of the upload
}
return myXhr;
},
data: formData[0],
cache: false,
processData: false, // Don't process the files
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
success: function(data, textStatus, jqXHR)
{
console.log('Data');
console.log(data);
if(typeof data.error === 'undefined')
{
// Success so call function to process the form
}
else
{
// Handle errors here
console.log('ERRORS: ' + data.error);
}
},
error: function(jqXHR, textStatus, errorThrown)
{
// Handle errors here
console.log('ERRORS: ' + errorThrown);
// STOP LOADING SPINNER
}
});
}
Server (Node.js)
//Route handler for template file uploaded
router.post('/template/upload', function(req, res) {
console.log('Uploading Files');
console.log(req.files);
});
Now the issue is that when I select a file and click the upload button, an ajax request is made. I have logged the data that I am sending and seems good at the client end. On server side there are however two issues.
(Issue solved by answer from #Scimonster)I don't see any file in req.files param. I did this before in Express 3.x without any issues. Now I am using Express 4.x, and maybe I am missing something.
The second issue is that when the request is sent to server, the terminal immediately logs the console.log('Uploading Files') message. But I don't receive any error or success message on client side. I also don't see in terminal that a POST request was received for the mentioned route. However after 2 minutes (every time), the terminal logs the request received for the route including the console.log() message. And this is when I get a response on client side.
Terminal Logging:
Uploading Files
undefined
POST /dashboard/template/upload 200 **120004ms**
Uploading Files
undefined
This is beyond me. I don't think there are any pre-flight checks generated by client side.If someone can provide insight as to what might the issue be, that'd be great.
req.files from Express 3 is from the body parser middleware. In 4.x, this is no longer packaged with Express. You can install multer and include it as explained in the docs to enable req.files.

Resources