Unable to upload Image to backend using multer - node.js

I was working on a small project on backend using nodeJS. I want to upload image to backend. I'm using nodeJS for backend and using packages like express, body-parser & multer.
I build a simple project to upload image, for now I just want that image is uploaded & stored in "public" folder that is in same level as server.js
server.js file
const express = require('express')
const multer= require('multer')
const path= require('path')
const bodyParser= require('body-parser')
const app = express()
const storage= multer.diskStorage({
destination: (req,file,cb)=>{
cb(null,"public")
},
filename: (req,file,cb)=>{
console.log(file);
cb(null, Date.now()+'-'+file.originalname);
}
})
app.use( bodyParser.urlencoded({ extended: true }) );
const uploads= multer({storage:storage})
app.post('/upload', uploads.single('image'), (req, res){
res.sendFile(req.file) // just send back json data of file that is uploaded
})
app.get('/',(req,res) =>{
res.sendFile(path.resolve(__dirname,'./index.html'))
});
app.listen(8000, ()=> console.log('Server Running at port: 8000'))
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="image">
<input type="submit">
</form>
</body>
</html>
I've also created a 'public' folder for storing files. Tried all possible ways available, read official document, watched videos but I'm unable to get it right. When I'm sending a post request I'm able to get data as req.body but I'm not getting req.file, I want to take the file that is uploaded in post request and save it in public folder.

try setting up destination path with path module, like on the GET route below.
try this:
const express = require('express')
const multer = require('multer')
const path = require('path')
const bodyParser = require('body-parser')
const app = express()
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.join(__dirname, 'public'))
},
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname);
}
})
app.use(bodyParser.urlencoded({
extended: true
}));
const uploads = multer({
storage: storage
})
app.post('/upload', uploads.single('image'), (req, res) => {
console.log('uploaded:', req.file);
res.sendFile(req.file.path);
// or
//res.download(req.file.path);
})
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'))
});
app.listen(8000, () => console.log('Server Running at port: 8000'))

Related

Multer nodejs - req.file is undefined

I am creating an app using Node, Express and ejs and multer for uploading images. Every time I submit the form, req.file is undefined. I've spent the entire day troubleshooting but can't figure out what I'm doing wrong.
HTML
<form action="/post" id="formPost" method="post" enctype="multipart/form-data">
<input class="img-file" type="file" name="image" required>
<input class="submit" type="submit" value="Post" />
</form>
app.js
const path = require('path');
const express = require('express');
const morgan = require('morgan');
const bodyParser = require("body-parser");
const multer = require('multer');
const app = express();
app.use(express.static(path.join(__dirname, 'public')))
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname,'resources/views'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./image");
},
filename: function (req, file, cb) {
console.log(req.file);
cb(null, Date.now() + "-" + file.fieldname + ".png");
},
});
const upload = multer({ storage: storage });
app.post("/post", upload.single("image"), (req, res) => {
console.log(req.file);
});
app.get("/post", (req, res) => {
res.render("post");
});
app.listen(, () => {
console.log(`Example app listening at http://localhost:3000/login`);
});
You have few little bugs: first you forgot to add port and instead of login it should be post then we hit the correct address immediately, avoiding error Cannot GET /login
app.listen(3000, () => {
console.log(`Example app listening at http://localhost:3000/post`);
});
Project Folder & File structure:
app.js I added simple an error handler to the:
app.post("/post", upload.single("image"), (req, res, next) => {}
const path = require("path");
const express = require("express");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const multer = require("multer");
const app = express();
app.use(express.static(path.join(__dirname, "public")));
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "resources/views"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./image");
},
filename: function (req, file, cb) {
console.log(req.file);
cb(null, Date.now() + "-" + file.fieldname + ".png");
},
});
const upload = multer({ storage: storage });
// app.post("/post", upload.single("image"), (req, res) => {
// console.log(req.file);
// });
app.post("/post", upload.single("image"), (req, res, next) => {
const file = req.file;
if (!file) {
const error = new Error("Please upload a file");
error.httpStatusCode = 400;
return next(error);
}
res.send(file);
console.log("Success", req.file);
});
app.get("/post", (req, res) => {
res.render("post");
});
app.listen(3000, () => {
console.log(`Example app listening at http://localhost:3000/post`);
});
post.ejs
<form action="/post" id="formPost" method="post" enctype="multipart/form-data">
<input class="img-file" type="file" name="image" required />
<input class="submit" type="submit" value="Upload File" />
</form>
output:
after selecting the file and pressing upload file:
VSCode output:
Works like a charm ;-)

Node.JS + Express parse CSV file on server

Essentially, what I have is a form where a user will upload a CSV file.
<form action="/upload" method="POST" enctype="multipart/form-data">
<div class="custom-file">
<input type="file" class="custom-file-input" id="customFile" name="file" required>
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
<input type="submit" class="btn btn-primary btn-block">
</form>
FYI: I'm using getbootstrap.com as my style sheet.
Now, the form sends a POST request to /upload which is where my node.js code is. What I need is for the server to parse this CSV file and extract the data. I've got no idea what to do as all the different NPM packages such as Multer are using a system where the save the file locally and then parse it.
Edit: Forgot to mention this, but temporary local CSV hosting is not an option.
I need the client to upload server to process it and push to a DB, can't save the file locally anywhere.
Edit 2: I've used multer and the memory processing option and have gotten the following.
const express = require("express");
const app = express();
var bodyParser = require("body-parser");
var multer = require('multer');
var storage = multer.memoryStorage();
var upload = multer({ storage: storage });
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));
app.get("/", function(req, res) {
response.sendFile(__dirname + "/views/index.html");
});
app.post("/upload", upload.single('file'), async (req, res) => {
res.send(req.file)
});
const listener = app.listen(process.env.PORT, function() {
console.log("Your app is listening on port " + listener.address().port);
});
Now once I upload the file, I'm getting the following response (this is what req.file is).
{"fieldname":"file","originalname":"tech.csv","encoding":"7bit","mimetype":"application/octet-stream","buffer":{"type":"Buffer","data":[67,76,65,83,83,32,73,68,44,84,69,67,72,32,35,44,70,73,82,83,84,32,78,65,77,69,44,76,65,83,84,32,78,65,77,69,13,10,54,79,44,54,79,48,49,44,65,110,105,115,104,44,65,110,110,101]},"size":56}
So It's pretty clear that our data happens to be
67,76,65,83,83,32,73,68,44,84,69,67,72,32,35,44,70,73,82,83,84,32,78,65,77,69,44,76,65,83,84,32,78,65,77,69,13,10,54,79,44,54,79,48,49,44,65,110,105,115,104,44,65,110,110,101
but how do I process that? The csv file data was
CLASS ID,TECH #,FIRST NAME,LAST NAME
6O,6O01,Anish,Anne
So how do I go from the information provided in the buffer data attribute to the actual data?
All you have to use is Multer. Multer will return a buffer object which you can then make a string with the .toString() attribute.
Code:
const express = require("express");
const app = express();
var bodyParser = require("body-parser");
var multer = require('multer');
var storage = multer.memoryStorage();
var upload = multer({ storage: storage });
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));
app.get("/", function(request, response) {
response.sendFile(__dirname + "/views/index.html");
});
app.post("/upload", upload.single('file'), async (req, res) => {
var b = req.file["buffer"]
console.log(b.toString())
res.send(b.toString())
});
const listener = app.listen(process.env.PORT, function() {
console.log("Your app is listening on port " + listener.address().port);
});

how to upload and read a file with express

I have question.I've looked at some questions here, but I can't get the answer.My question is, I want to upload and read a json file, I try with "multer" but couldn't.So I want to put the file I upload to the result variable. Can you help me? How can I achieve this?
HTML;
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<form action="/import" enctype="multipart/form-data" method="post">
<input type="file" name="filename">
<input type="submit" value="Upload">
</form>
</body>
</html>
Server.js
const express = require('express');
const multer = require('multer');
const upload = multer({
dest: 'uploads/' // "uploads"
});
const app = express();
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
route.post("/import", upload.single("filename") (req, res, next) => {
var result = require(# I want to send the json file I uploaded here, and I need to see the contents of the json file as is #)
res.json(result)
res.redirect("/")
});
app.listen(3000);
The upload.single() parses the data stream and saves as a file based on the configuration. In your case, it will look for filename field in the incoming request and save the file in the uploads/ folder. The metadata of the file is available in req.file object. You can simply do console.log(req.file) to see the information.
To read the content of the file, you can use req.file.path field. Here is how:
const fs = require("fs");
const path = require("path");
/** In the controller */
const absolutePath = path.join(__dirname, req.file.path);
const jsonString = fs.readFileSync(absolutePath, "utf-8");
const jsonObject = JSON.parse(jsonString);
console.log(jsonObject);
Here is how the complete server.js would look like:
const express = require("express");
const multer = require("multer");
const fs = require("fs");
const path = require("path");
const upload = multer({
dest: "uploads/" // "uploads"
});
const app = express();
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
const route = express.Router();
route.post("/import", upload.single("filename"), (req, res, next) => {
console.log(req.file);
const absolutePath = path.join(__dirname, req.file.path);
const jsonString = fs.readFileSync(absolutePath, "utf-8");
const jsonObject = JSON.parse(jsonString);
console.log(jsonObject);
res.redirect("/");
});
app.use(route);
app.listen(3000);
I have added some parts which were missing from your snippet ( like express.Router ). They might be different though.

Express not serving static files correctly for react build

I'm new to react. I've been trying to convert my MEAN stack app to an express and reactjs app but I'm having problems getting my build files to come in correctly. It looks like my server is loading my index.html file in place of my js files. Can anyone help me figure out why?
I've got the following error in my main.js in the browser: Uncaught SyntaxError: Unexpected token <
My files are built into a build folder which is a sibling to my server.js file.
mywebsite (root)
-src (f)
-build (f)
-server.js
-public (f)
Here's my server.js
require('./server/config/config');
// Get dependencies
const express = require('express');
const morgan = require('morgan');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const api = require('./server/routes/api');
const compression = require('compression')
const app = express();
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url
HTTP/:http-version" :status :res[content-length] :response-time ms'));
// Serve static assets
app.use(express.static(path.join(__dirname, 'build')));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);
app.get('/robots.txt', function (req, res) {
res.type('text/plain');
res.send("User-agent: *\nDisallow: /");
});
// Always return the main index.html
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
});
const port = process.env.PORT || '3001';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`API running on
localhost:${port}`));
module.exports = app;
here's the generated index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-
fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="/brookeclonts/brookeclonts.com/manifest.json">
<link rel="shortcut
icon" href="/brookeclonts/brookeclonts.com/favicon.ico">
<title>React App
</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="text/javascript" src="/brookeclonts/brookeclonts.com/static/js/main.9ffbadeb.js">
</script>
</body>
</html>
Let me know if you see something I'm not seeing. I'm going in circles. Thanks in advance!
You can also merge directories as:
// Serve static assets
app.use('public', express.static(path.join(__dirname, 'build')));
app.use('public', express.static(path.join(__dirname, 'public')));
// Always return the main index.html
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'index.html'));
});
What was posted here was close to the answer. Thank you for your help everyone! My real problem was that I had forgotten about the .htaccess file. See: https://github.com/facebook/create-react-app/issues/1171 and https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#deployment

ExpressJs View helpers do not work

It's probably a newbie question. I'm trying to setup my very first expressjs application and I need to use a view helpers that doesn't work for some reason.
Here is my server.js
var express = require('express');
var app = express();
var test = function(req, res, next) {
res.myLog = function(){
console.log("res");
return "Hello";
}
next();
}
app.use(test);
app.get("*", function(req, res) {
res.sendfile('./dist/index.html');
})
app.listen(5000);
And index.html
<html>
<head>
<title>Test application</title>
<link rel="stylesheet" href="main.css" />
<script src='<%=myLog()%>'></script>
</head>
<body>
<h1>Yo World!</h1>
</body>
</html>
myLog function is not call during rendering. Originally I was trying to use some third part helpers and they didn't work as well.
I haven't found any documentation of how to use the helpers on expressjs site. I'm clearly doing something wrong here.
Express version 4.3.14
To send file using express, correct ways is:
//sending html files
var express = require('express');
var app = express();
var path = require('path');
// viewed at http://localhost:5000
app.get('/', showClientRequest, function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
function showClientRequest(req, res, next) {
var request = {
REQUEST : {
HEADERS: req.headers,
BODY : req.body
}
}
console.log(request)
return next();
}
app.listen(5000);
Use ejs template engine:
var express = require('express');
var ejs = require('ejs');
var app = express();
app.set('view engine', 'ejs');
var path = require('path');
// viewed at http://localhost:5000
app.get('/', showClientRequest, function(req, res) {
res.render('index',{message:"Hello World!"});
});
function showClientRequest(req, res, next) {
console.log('Something Here...');
return next();
}
app.listen(5000);
Node-Cheat Available:
For complete code, get working node-cheat at express_server run node app followed by npm install express ejs.
Use res.locals.myLog instead of res.myLog to set locals. If you don't need req within your helper function you can also use app.locals.myLog.
res.sendfile will not render your view but just send a file as it is. You will have to use res.render and move your dist/index.html to views/index.ejs.

Resources