I want to upload an image in a vuejs storage with an API built with NodeJS and Express.
So I found a tutorial
First, I ran the command
npm install express-fileupload
and I added
const fileUpload = require('express-fileupload');
app.use(fileUpload());
my code for API (nodeJS & Express) :
const port = 000; // for security!
const express = require('express');
var app = express();
const mysql = require("mysql");;
const path = require('path');
const nodemailer = require('nodemailer');
var cors = require('cors');
app.use(cors());
const res = require('express/lib/response');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const { PrismaClient, Type } = require('#prisma/client');
const prisma = new PrismaClient();
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const htmlspecialchars = require("htmlspecialchars");
const striptags = require("striptags");
const { accessSync } = require('fs');
const fileUpload = require('express-fileupload');
app.use(fileUpload());
app.post('/upload', (req, res) => {
console.log('jentre dans mon upload') ;
// Get the file that was set to our field named "image"
var { image } = req.files;
console.log(req.files);
// If no image submitted, exit
//if (!image) return res.sendStatus(400);
// If does not have image mime type prevent from uploading
//if (/^image/.test(image.mimetype)) return res.sendStatus(400);
// Move the uploaded image to our upload folder
//console.log(__dirname + '/src/components/upload/' + image.name);
//image.mv(__dirname + '/src/components/upload/' + image.name);
// All good
res.sendStatus(200);
});
my folders :
In my front a make a form :
<form action="http://localhost:195/upload" method="POST" enctype="form-data">
<input type="file" name="image" />
<button type="submit">Upload</button>
</form>
my page :
So, when i want to upload an image i have this error :
"jentre dans mon upload
TypeError: Cannot destructure property 'image' of 'req.files' as it is undefined."
(the same error appeared in my terminal for the api)
I don't understand this error, why req.files is not defined...
Thank you for your help and have a good day !
Related
Hi everyone facing issue for API not getting called from node(express.js).
When i call it using controller file it returns status 200 with data=[] empty array and does not print in console ' [] ' but when i call the same API in the product.js(API file) it gets called
gives response as status 200 and data=hi
i have disabled app.disable("etag"); in app.js
Calling Api from react.js to Express.js API
export const getRandomProductAPI = () => Axios.get(`${url}/v1/product/getRandomProduct`);
I am having API folder in which i am reciving the request from react.js in Product.js(API file).
const express = require("express");
const router = express.Router();
const multer = require("multer");
const productController = require("../controllers/ProductController");
const storage = multer.memoryStorage({
destination: function (req, file, callBack) {
callBack(null, "");
},
});
const uploadProduct = multer({ storage }).single("productImage");
const updateProduct = multer({ storage }).single("newEditImage");
// router.get("/getRandomProduct", (req, res) => {
// res.status(200).send("hi");
// });
router.post("/add", uploadProduct, productController.addProduct);
router.get("/:category", productController.getProduct);
router.delete("/:id/:imageName", productController.deleteProduct);
router.patch("/", updateProduct, productController.updateProduct);
router.get("/Id", productController.getLatestProductId);
router.get("/getRandomProduct", productController.getRandomProduct);
module.exports = router;
API which is got called is the last one-> router.get("/getRandomProduct",roductController.getRandomProduct);
Controller Code ProductController.js
const getRandomProduct = async (req, res) => {
console.log("called");
res.status(200).send("hi");
};
module.exports = {
addProduct,
getProduct,
deleteProduct,
updateProduct,
getLatestProductId,
getRandomProduct,
};
App.js code
const express = require("express");
const morgan = require("morgan");
const helmet = require("helmet");
const cors = require("cors");
const path = require("path");
require("dotenv").config();
const middlewares = require("./middlewares");
const api = require("./api");
const app = express();
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client/build")));
}
app.use(morgan("dev"));
app.use(helmet());
app.use(cors());
app.use(express.json());
// app.disable("etag");
app.get("/", (req, res) => {
res.json({
message: "🌎🌍🌏 Furnitures ",
});
});
app.use("/v1", api);
app.use(middlewares.notFound);
app.use(middlewares.errorHandler);
module.exports = app;
I have a node express set up.
While using Postman, Iam able to see data sent through x-www-form-urlencoded but the same is not being shown through form-data.
below are the codes
Server.js
const express = require('express')
var cors = require('cors')
const app = express()
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
var cookieParser = require('cookie-parser')
app.use(cookieParser())
app.use(cors())
const index = require("./routes/index")
app.use("/", index)
const port = process.env.PORT || 3060;
app.listen(port, function listenHandler() { console.log(`Running on ${port}`) });
Index.js
const express = require('express')
const router = express.Router()
var pool = require('./mysqlConnector')
const asyncMiddleware = require('./asyncMiddleware')
const func = require('./functions')
const time = new Date().toISOString().slice(0, 19).replace('T', ' ')
const nodemailer = require("nodemailer");
router.use('/auth', require('./auth')
Auth .js
const express = require('express')
const router = express.Router();
var pool = require('./mysqlConnector')
const asyncMiddleware = require('./asyncMiddleware')
const jwt = require('jsonwebtoken')
const bcrypt = require('bcryptjs')
const nodemailer = require("nodemailer");
const func = require('./functions')
router.post('/register', asyncMiddleware( async(req, res, next) => {
res.send({ success: true, message: req.body })
}))
You should use Multer to handle form-data.
Multer is a node.js middleware for handling multipart/form-data
body-parser middleware can't handle multipart/form-data.
This does not handle multipart bodies, due to their complex and typically large nature.
In case you need to handle a text-only multipart form, you should use the .none() method:
E.g.
const express = require('express');
const bodyParser = require('body-parser');
const multer = require('multer');
const upload = multer();
const app = express();
app.use(upload.none());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/auth/register', (req, res) => {
res.send({ success: true, message: req.body });
});
const port = process.env.PORT || 3060;
app.listen(port, function listenHandler() {
console.log(`Running on ${port}`);
});
postman:
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const MongoClient = require("mongodb").MongoClient;
const app = express();
app.use(bodyParser.json());
app.use(cors());
app.post("/addProducts", (req, res) => {
const file = req.files.file;
const newImg = file.data;
const encImg = newImg.toString("base64");
var image = {
contentType: req.files.file.mimetype,
size: req.files.file.size,
img: Buffer.from(encImg, "base64"),
};
productCollection
.insertOne({ image })
.then((result) => {
res.send(result.insertedCount > 0);
});
});
I'm trying to save an image in MongoDB, but this code is backdated. They are using another npm package. Any help would be appreciated. I do not use a path for sending image.
I am creating an app using Node, Express and Handlebars 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.
Router File:
const express = require('express');
const router = express.Router();
const multer = require('multer');
const mongoose = require('mongoose');
const path = require('path');
const methodOverride = require('method-override');
//Set Storage Engine
const storage = multer.diskStorage({
destination: './public/uploads/images',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() +
path.extname(file.originalname));
}
});
const upload = multer({
storage: storage
}).single('featuredImage');
//Change Featured Image - POST
router.post('/saveImage/:id', (req, res) => {
console.log(req.file);
//removed the rest of the code to keep it simple. req.file here is always undefined.
});
Form
<form action="/saveImage/{{pitch.id}}" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="featuredImage">Featured Image</label>
<input type="file" name="featuredImage" id="featuredImage">
</div>
<input type="submit" value="SAVE">
</form>
app.js these requires are in the app.js file.
const express = require('express');
const exphbs = require('express-handlebars');
const path = require('path');
const passport = require('passport');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const flash = require('connect-flash');
const session = require('express-session');
const methodOverride = require('method-override');
const nodemailer = require('nodemailer');
//Set StaticFolder
app.use(express.static(path.join(__dirname, 'public')));
You need to add upload.single('featuredImage') as middleware for the respective route as follows.
const upload = multer({storage: storage});
//Change Featured Image - POST
router.post('/saveImage/:id',upload.single('featuredImage'), (req, res) => {
console.log(req.file);
//removed the rest of the code to keep it simple. req.file here is always undefined.
});
In my case it was issue with image size. I resolved it with defining multer limit as follows:
const upload = multer({ storage: storage, limits: { fieldSize: 10 * 1024 * 1024 } }); //10MB
Took me ages to figured out.
Maybe this can help someone
Please refer to this question. It has answer you are looking for.
node js multer file upload not working. req.file and req.files always undefined
You have to pass middleware
router.post('/saveImage/:id', upload.single('featuredImage'), (req, res) => {
console.log(req.file);
});
At first I was having the same issue! But when I added this :
const { storage } = require ('debug/src/browser');
... it worked.
This is my multer code :
const { storage } = require('debug/src/browser');
const multer = require('multer');
const MINE_TYPES = {
'image/jpg' : 'jpg',
'image/jpeg': 'jpeg',
'image/png':'png'
}
const Storage = multer.diskstorage({
destination: (req, file, callback)=>{
callback(null, "public/images/articles")
},
filename: (req, file, callback) => {
var name = Math.floor(Math.random() * Math.floor(15258652325)).tostring()
name = Math.floor(Math.random() * Math.floor(15258652325)).toString();
name = Math.floor (Math.random() * Math.floor(15258652325)).toString();
name = Math.floor(Math.random() * Math.floor(15258652325)).tostring();
name = Math.floor(Math.random() * Math.floor
(15258652325)).toString();
name += Date.now();
const extension = MINE_TYPES[file.mimetype];
name += extension;
callback(null,name);
module.exports = multer({ storage: Storage)).
single('image');
I was facing the same issue and you can solve it by following these steps:
1- First add these line in your server.js or index.js root file
app.use(express.json());
app.use(express.urlencoded({
extended: true,
})
);
2- Create a folder name middleware and inside it create a file name upload.js or any name that you want.
3- Place the following code in upload.js file
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "public/");
},
filename: function (req, file, cb) {
const imgName = file.originalname;
cb(null, imgName );
},
});
const upload = multer({
storage: storage,
});
module.exports = upload;
4- Now you can use this middleware in any route. For example:
const upload = require("../middlewares/fileUpload");
router.route("/send").post(upload.single("profile"),
((req,res) => {
*your controller logic here*
});
**Note: Here profile is the name of the file key that you are sending**
Use this:
var fileupload = require("express-fileupload");
app.use(fileupload());
I am trying to put a file into a s3 bucket from my node server using a post request in node.js. Here is the part of my node server that sets up the routes.
// Get Dependencies
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
// Get API Routes
const api = require('./server/routes/api');
const app = express();
// Parse for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// post static path to dist
app.use(express.static(path.join(__dirname,'dist')));
// Set our api routes
app.use('/api', api);
Here is api.js
const express = require('express');
const router = express.Router();
var fs = require('fs');
var S3FS = require('s3fs');
var s3fsImp1 = new S3FS('bucketname',{
accessKeyId: 'xxxxxxxxx',
secretAccessKey: 'xxxxxxxxxxxx'
});
router.get('/',(req,res) => {
res.status(200).json({ message: 'Connected!' });
});
router.post('/upload',(req,res) => {
var file = req.body.file;
console.log(file);
var stream = fs.createReadStream(file)
return s3fsImpl.writeFile(file,stream).then(function(){
fs.unlink(file,function(err){
if(err)
console.error(err);
});
res.send('done');
}).catch(function (err) {
return res.status(500).send({
message: errorHandler.getErrorMessage(err)
});
});
});
module.exports = router;
Node throws the error ReferenceError: s3fsImpl is not defined when I call that post method from postman. Any help would be appreciated.