express upload file with multer not working with urlencodedParser - javascript

I am trying to upload an image with a post request form. In my express.js server I am both using multer and urlencodedParser, because I am passing all the html inputs as a json object through the post request body plus a selection of a file, which I am handeling it with multer.
Here is the HTML code for the form:
<form action="http://localhost:8000/api/addOrgs" method="post">
<div class="form-row">
<!-- OTHER CODE -->
<div class="form-group col-md-6">
<label>Image or Logo</label>
<input type="file" class="form-control" name="image" id="fileToUpload">
</div>
<button class="btn btn-primary"> Add the organization to the system</button>
</div>
</form>
I have set up the multer:
// add image to folder
var multer = require('multer')
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../public/images/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
var upload = multer({ storage: storage })
Here is the express post request handler:
// to add a new organization to the list
app.post('/api/addOrgs', upload.single('imageToUpload'), urlencodedParser, (req, res)=> {
try {
var newobj = req.body;
// want to change name of id in obj
// add image name and delete image field
newobj['img'] = newobj.image;
delete newobj.image;
// read orgs file
let orgs = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../orgs.json')));
//... OTHER CODE
// send respond
res.send('<h1>Successfully added!</h1><br><p>'+JSON.stringify(newobj, null, 4)+'</p></br><b>Now you can go BACK</b>')
// OTHER CODE
} catch (e) {
// ... OTHER CODE
}
});
The problem is that I successfully have the name of the file uploaded in the json object sent through the req.body but it does NOT save the file in the folder. Is the problem coming from the usage of urlencodedParser for the app.post() parameter?
Or do I have to do something in order to save the file inside my app.post() function?

The file's form should have enctype="multipart/form-data" attribute. Try this, and it should work

Related

How to store an html input image file to a file locally on the server

I want to store the image uploaded in a simple html input
<input
type="file"
name="thumbnail"
id="image-input"
accept="image/png, image/jpg, image/jpeg"
hidden
/>
This leads to a post request when submitted
router.post('/dish/new',async (req,res) => {
let { name, desc, cost, isnonveg, thumbnail} = req.body;
fs.writeFile(path.join(__dirname,'../userdata/images/dishes','g.jpg'),thumbnail, ()=>{
console.log('image stored')
})
})
I want to store whatever the user uploads using node fs
How can I go about doing this.
The approach I use here merely stores the name of the file instead of the actual file.
if you are using express you can add this attribute to form tag enctype="multipart/form-data". Then your image will be sent from frontend . To receive the image in the server you need to configure a middleware called express-fileupload
var fileupload = require("express-fileupload");
then you can register the middleware by app.use(fileupload()); in your app.js file
in your route file
router.post('/something', async (req, res) => {
let image=req.files.fieldName
})
image.mv('./public/images/foldername/' + 'imageName' + '.jpg', (err) => {
if (err) {
console.log(err)
} else {
res.redirect('/)
}})
once it is done when you submit your form you can see the uploaded image in your server /public/images/foldername .

cannot access the POST form data sent by HTML/Javascript code at node js code

I made a simple nodejs server which serves a html page to the user.The page contains a input text box of userID. When the user presses the button submit, I take that userID entered by the user and put it in form Data and send it to my server function (submitForTest) through POST method.
Now, inside my function of nodejs which handles submitForTest, I tried to access the userID , but I was getting res.body as {} , so not able to figure out how to access userID here.
Can anyone please point what I need to get the userID at my node js code.
My HTML file :
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
<label>User ID</label>
<div>
<input type="text" id="userid" >
</div>
</div>
<div>
<div>
<button type="submit" onclick="submitForTest()">Submit</button>
</div>
</div>
<script type="text/javascript">
function submitForTest()
{
var userID = document.getElementById('userid').value;
let formData = new FormData();
formData.append("userID", userID);
//alert("hello");
fetch('http://MY-SERVER:3000/submitForTest', {method: "POST", body: formData});
}
</script>
</body>
</html>
My Node js file :
'use strict'
const fs = require("fs")
const express = require('express')
var path = require('path')
const app = express()
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
var jsonParser = bodyParser.json();
app.get('/',function(req,res) {
res.sendFile('small.html');
});
app.post('/submitForTest', function(req, res) {
//want to print userID here .. but the below is coming as {} here ..
console.log(req.body);
})
// Tell our app to listen on port 3000
app.listen(3000, function (err) {
if (err) {
throw err;
}
console.log('Server started on port 3000')
})
Please help.
Regards
The problem is FormData is sending body encoded as multipart/form-data. You'll have to add middleware able to handle multipart body format. Busboy or multer for example.
Example of using multer to upload a file and send userID field:
// --- form
<form action="/submitForTest" enctype="multipart/form-data" method="post">
<input type="file" name="uploaded_file">
<input type="text" name="userID">
<input type="submit" value="Submit">
</form>
// --- server
var multer = require('multer')
var upload = multer({ dest: './uploads/' }) // where the uploaded files will be stored
app.post('/submitForTest', upload.single('uploaded_file'), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body)
});
Or to send your data in urlencoded or json format. Something like that for json for example:
function submitForTest()
{
var userID = document.getElementById('userid').value;
fetch('http://MY-SERVER:3000/submitForTest', {
method: "POST",
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({ userID }),
});
}

How to send pdf file from front-end to Nodejs server?

I have a pdf generated file on the front end of my application that I got using html2pdf plugin. I have a nodemailer server at my backed where I can attach files and send it to an email of my choice. Is there a way I can send the pdf that is generated in the front end to Nodejs? I am also using express
Edit:
Based on your advice I did
**On the Client side**
var element = document.getElementById('element-to-print');
const elem = document.getElementById('html');
html2pdf().from(element).toPdf().get('pdf').then(function (pdf) {
window.open(pdf.output('bloburl'), '_blank');
var formData = new FormData();
formData.append("filename", pdf);
axios.post('/upload',formData).then(res => { console.log(res) })
// formData.append("uploadedFile", fileInputElement.files[0]);
})
On express app
app.post('/upload', fileUpload(), function(req, res) {
const sampleFile = req.files.uploadedFile;
// do something with file
res.send('File uploaded');
})
But I get this error coming from index.js
TypeError: Cannot read property 'uploadedFile' of null
Yes.
Create and endpoint/route in your express app
Use a http agent like superagent, request or axios in your client
Use multipart form or something like FormData to create the data that is supposed to be sent.
Post it to the url you created in express.
Use middlewere such as express-fileupload or busboy to handle the attachment.
So in your client. You have something like
var formData = new FormData();
formData.append("filename", "My awesome file");
formData.append("uploadedFile", fileInputElement.files[0]);
Then you post that with something like Axios
axios.post('/upload',formData).then(res => { console.log(res) })
In your express app you do something like
const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
app.post('/upload', fileUpload(), function(req, res) {
const sampleFile = req.files.uploadedFile;
// do something with file
res.send('File uploaded');
})
<form method="post" enctype="multipart/form-data" action="/">
<div>
<label for="profile_pic">Choose file to upload</label>
<input type="file" id="profile_pic" name="profile_pic"
accept=".pdf">
</div>
<div>
<button>Submit</button>
</div>
For receive it at node you have to define a new route at the same path.

node.js how to assemble file upload?

I'm writing an image upload in node.js, I have uploaded a file from the client:
<form id="frmImgUpload"
enctype="multipart/form-data"
action="/uploads/"
method="POST">
<input id="btnFile"
style="float:right;"
type="file"/>
<input id="btnUpload"
style="float:right;"
type="button"
value="Upload"/>
</form>
The code to perform the upload:
$("#btnUpload").click(function() {
$("#btnFile").attr("name", strCompanyKey);
$("#frmImgUpload").submit();
});
On the server I have displayed the data (just a small snippet):
[ '------WebKitFormBoundaryI206ASCJdnqVyOo0\r\nContent-Disposition: form-data; name="syberdyne"; filename="simonplatten.png"\r\nContent-Type: image/png\r\n\r\n�PNG\r\n\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0000�\u0000\u0000\u0000l\b\u0006\u0000\u0000\u0000Ԃ\b�\u0000\u0000\u0000\tpHYs\u0000\u0000\u000b\u0013\u0000\u0000\u000b\u0013\u0001\u0000��\u0018\u0000\u0000\nOiCCPPhotoshop ICC profile\u0000\u0000xڝSgTS�\u0016=���BK���KoR\u0015\b RB��\u0014�',
'*!\t\u0010J���\u0015Q�\u0011EE\u0004\u001bȠ�\u0003����\u0015Q,\f�\n�\u0007����������{�kּ������>������\u0007�\b\f�H3Q5�\f�B\u001e\u0011�������.#�\n$p\u0000\u0010\b�d!s�#\u0001\u0000�<<+"�\u0007�\u0000\u0001x�\u000b\b\u0000�M��0\u001c��\u000f�B�\\\u0001��\u0001�t�8K\b�\u0014\u0000#z�B�\u0000#F\u0001���',
What I would like to do is reassemble this data into the original file. Are they're any API's or tutorials that will help me to achieve this?
I've split the content received from the client:
var strBody = "";
request.on("data", function(chunk) {
strBody += chunk;
});
request.on("end", function() {
console.dir(strBody.split("\r\n"));
});
This results in:
[ '------WebKitFormBoundarynBkMCKI8RBvIReTF',
'Content-Disposition: form-data; name="syberdyne";filename="simonplatten.png"','Content-Type: image/png','','�PNG','\u001a\n\u0000\u0000\u0000\rIHDR\u0000\u0000\u0000�\u0000\u0000\u0000l\b\u0006\u0000\u0000\u0000Ԃ\b�\u0000\u0000\u0000\tpHYs\u0000\u0000\u000b\u0013\u0000\u0000\u000b\u0013\u0001\u0000��\u0018\u0000\u0000\nOiCCPPhotoshop ICC profile\u0000\u0000xڝSgTS�\u0016=���BK���KoR\u0015\b RB��\u0014�&*!\t\u0010J���\u0015Q�\u0011EE\u0004\u001bȠ�\u0003����\u0015Q,\f�\n�\u0007����������{�kּ������>������\u0007�\b\f�H3Q5�\f�B\u001e\u0011�������.#�001\u0000O��y���7\u0000\u0000\u0000\u0000IEND�B`�',
'------WebKitFormBoundarynBkMCKI8RBvIReTF--',
'' ]
This is just a snippet of the data, it looks like the binary data is encoded somehow, is there a routine I can call to decode it?
I've installed 'formidable', what do I parse it?
You could use multer package: https://www.npmjs.com/package/multer
Multer adds a body object and a file or files object to the request object. The body object contains the values of the text fields of the form, the file or files object contains the files uploaded via the form.
Example:
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/profile', upload.single('avatar'), function (req, res, next) {
// req.file is the `avatar` file
// req.body will hold the text fields, if there were any
})
Formidable is "a node.js module for parsing form data, especially file uploads."
According to its documentation, you pass requests in and it allows you to access the form data conveinently via a callback function or through events.
Via optional callback:
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
// ...
});
And via events:
var form = new formidable.IncomingForm();
form.on('error', function(err) {
// ...
});
form.on('field', function(name, value) {
// ...
});
form.on('file', function(name, file) {
// ...
});
form.parse(req);

Where would a file be located on my Node.js + Express server if I send a CSV file to the server using jQuery's ajax method?

I am sending a CSV file to my node + express server using jQuery's ajax POST method. When I post the csv file to my express route, I don't know how to access the file once it reaches the server. My goal is to pass the CSV file into my route's middleware called upload.single(). I'm also not sure which data type to specify for the ajax call.
Here is my form where I accept the CSV file:
<form onSubmit={this.handleSubmit.bind(this)} encType="multipart/form-data">
<input id="userFile" type="file" name="userFile"></input>
<input type="submit" name="submit" value="Upload New Candidates"></input>
</form>
Here is my handleSubmit function which makes the POST request:
handleSubmit(event) {
event.preventDefault();
var csvToSend = document.getElementById("userFile").files[0];
$.ajax({
type: "POST",
url: 'http://localhost:3000/',
data: csvToSend,
success: success,
dataType: //not sure what to put here
});
}
Here is my express route on the server. How should I access the CSV file sent from the client and enter it into the upload.single() middlware?
app.post('/', upload.single('userFile'), function(req, res, next) {
res.sendStatus(200);
});
As peteb mentioned it looks like you're using multer for a single file and so in that situation:
// If you set up multer to store files locally
const upload = multer({ dest: 'uploads/' });
const fs = require("fs");
app.post('/', upload.single('userFile'), async function(req, res, next) {
const filePath = req.file.path;
const fileData = await fs.promises.readFile(filePath); // Buffer of csv file
const csvString = fileData.toString();
// Do whatever you need to with the csv file
res.sendStatus(200);
});

Categories

Resources