req.file is undefined: uploading images in express using multer - node.js

I am trying to upload images in an express server using multer, however, uploading images using postman using the route below, gives the json message { msg: 'image uploaded successfully' } (i.e., the route is reached correctly), but req.file gives undefined. Why? the related file structure is as follows, to make sure I am referencing the destination correctly:
-backend
--routes
---uploadRoutes.js
--server.js
-frontend
-uploads
uploadRoutes.js
import path from 'path';
import express from 'express';
import multer from 'multer';
const router = express.Router();
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, 'uploads');
},
filename(req, file, cb) {
cb(
null,
`${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`
);
},
});
function checkFileType(file, cb) {
const filetypes = /jpg|jpeg|png/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = filetypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
cb('Images only!');
}
}
const upload = multer({
storage,
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
});
router.post('/', upload.single('image'), (req, res) => {
console.log(req.file);
try {
res.status(200).json({ msg: 'image uploaded successfully' });
} catch (error) {
console.error(error.message);
}
// res.send(`/${req.file.path}`);
});
export default router;

just check the header and body form-data request, because your code is correctly if you have this line in the app file
app.use("/uploads", express.static("uploads"));
header of request

Related

Delete original image from cloudinary

I am using cloudinary with node and multer
I successfully managed to store images but i noticed each time i upload an image it creates two copies : one with the public_id as a name (in the assets) and the other with the original name(in 'profiles' folder).
I want to delete both whenever i upload a new image but it only deletes the one in the assets and don't delete the one in the 'profiles' picture.
My upload route looks like this
import path from "path";
import express from "express";
import dotenv from "dotenv";
import cloudinary from "cloudinary";
import { CloudinaryStorage } from "multer-storage-cloudinary";
import multer from "multer";
dotenv.config();
const cloud = cloudinary.v2;
const router = express.Router();
cloud.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const storage = new CloudinaryStorage({
cloudinary: cloud,
params: {
folder: "profiles",
transformation: { gravity: "center", height: 300, width: 300, crop: "fill" },
public_id: (req, file) =>
`${file.originalname.split(".")[0]}-${Date.now()}`,
},
});
function checkFileType(file, cb) {
const filetypes = /jpg|jpeg|png/;
const extname = filetypes.test(
path.extname(file.originalname).toLocaleLowerCase()
);
const mimetype = filetypes.test(file.mimetype);
if (extname && mimetype) {
return cb(null, true);
} else {
cb(null, false);
}
}
const upload = multer({
storage,
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
});
router.post("/", upload.single("image"), async (req, res) => {
try {
const result = await cloud.uploader.upload(req.file.path)
res.send(result);
} catch(error) {
console.log(error)
}
});
export default router;
And the delete route
import express from "express";
import dotenv from "dotenv";
import cloudinary from "cloudinary";
dotenv.config();
const cloud = cloudinary.v2;
const router = express.Router();
cloud.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
router.post('/:id', async (req, res) =>{
try {
await cloud.uploader.destroy(req.params.id);
// await cloud.uploader.destroy(`/profiles/${req.params.id}`);
res.send(result);
} catch (err) {
return res.status(500).json({msg: err.message})
}
})
export default router;
Can anyone help ?
In case anyone face the same issue
I was sending the image twice in the upload route
Just change it to this
router.post("/", upload.single("image"), async (req, res) => {
try {
res.json(req.file);
} catch (error) {
console.log(error);
}
});

How to upload multi part data from forms to google drive using multer and google drive apis in node.js?

Currently the image gets stored in my upload folder. Since i am new to node.js and multer can anyone guide me on how to store these images to google drive?
https://developers.google.com/drive/api/v3/quickstart/nodejs
When through these link but dont know how to implement it in my project. The code provided in this link uploades an image to google drive but the path of the file has to be harcoded. Can anyone please help me out. I am beginner in back end development.
here is my code for reference
```
const express = require("express");
const router = express.Router();
const multer = require("multer");
const path = require("path");
//set storage engine
const storage = multer.diskStorage({
destination: "./public/uploads/",
filename: function(req, file, cb) {
cb(null,file.fieldname + "-" + Date.now() + path.extname(file.originalname));
}
});
//init upload
const upload = multer({
storage: storage,
limits: { fileSize: 10000000 },
fileFilter: function(req, file, cb) {
checkFileType(file, cb);
}
}).single("myImage");
//check file type
function checkFileType(file, cb) {
//Allowed ext
const fileTypes = /jpeg|jpg|png|gif/;
//check ext
const extname = fileTypes.test(
path.extname(file.originalname).toLocaleLowerCase()
);
//check mime
const mimetype = fileTypes.test(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
} else {
cb("Error: Images Only!");
}
}
router.get("/", (req, res) => res.render("./index"));
router.post("/upload", (req, res) => {
upload(req, res, err => {
if (err) {
res.render("index", {
msg: err
});
} else {
// console.log(req.file);
// res.send("test");
if (req.file == undefined) {
res.render("index", {
msg: "Error: No File Selected!"
});
} else {
res.render("index", {
msg: "File uploaded!",
file: `uploads/${req.file.filename}`
});
}
}
});
});
module.exports = router;
```

How to upload and save image to mongodb using node js

I am working on a project and i need to upload and save image to MongoDB. I using NodeJS as backend and Angular Material for frontend.
I am writing the node and angular in TypeScript. How this upload and save can happen. I want also to know how I can reed and display them.
Check Multer
example of use
store.js
import multer from 'multer';
const storage = multer.diskStorage({
destination: function (req, file, cb) {
const path = process.cwd() + '\\uploads';
cb(null, path);
},
filename: function (req, file, cb) {
cb(null, `file-${Date.now()}.${file.originalname.split(/[.]+/).pop()}`);
}
});
export const UploadHandler = multer({
storage: storage,
fileFilter(req, file, callback, acceptFile) {
if (['image/png'].indexOf(file.mimetype) === -1) {
return callback(new Error("This File Is Not Supported"), false);
}
return callback(null, true);
}
});
app.js
import store from './store';
app.post('/upload', store.array('files', 1), function (req, res, next) {
if(req.files && req.files.length > 0) {
// files uploaded successfully
}
});

Multer is not working outside of the http object

I am using multer and it works fine in the http object, here is the code:
server = http.createServer(function(req, res){
var upload = multer({ storage : multerhelper.storage}).single('userFile');
upload(req, res, function(err) {
if(err)
console.log("Error uploading the file");
});
});
The moment I take this piece of code outside of the http object inside another file, it doesn't work anymore.
handlers._users.post = function(req, res, data, callback){
var upload = multer({ storage : multerhelper.storage}).single('userFile');
upload(req, res, function(err) {
if(err)
console.log("Error uploading the file");
callback(400, {'Message' : 'Done'});
});
});
Your help is appreciated.
You can make a file which will have the multer logic and export this file so that you can get the multer functionality.
example:
const multer = require("multer");
// store the file reference through multer
const storage = multer.diskStorage({
destination: function (req, file, callback) {
//Where file should be store
callback(null, __base + "/public/uploads");
},
filename: function (req, file, callback) {
callback(null, file.originalname);
}
});
//make sure file is image as the jpeg or png
const fileFilter = (req, file, callback) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png" || file.mimetype === 'application/octet-stream') {
callback(null, true);
}
callback(null, false);
};
export const upload = multer({
storage,
limits: {
fileSize: 1024 * 1024 * 5000
},
fileFilter
});
Now import this file as
import {
upload
} from "/filepath";

How to handle errors with multer-s3

I am using multer-s3 to upload files to was S3. When i upload a file it all works fine and I have never had an error, however most tutorials do not mention anything about how to handle a case where there may be an issue with uploading files.
My upload is as follows
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'my bucket',
key: function (req, file, cb) {
console.log(file);
cb(null, file.originalname);
}
})
});
And i call it from the
app.post('/File/Add' , storage_functions.upload.single('file'), function (req, res) {
console.log('file uploaded')
});
does multers3 provide some kind of response on upload. This would be useful to access errors but would also be useful if the response contained the file path in s3.
You can add callback function to handle errors.
const upload = storage_functions.upload.single('file');
app.post('/File/Add', function (req, res) {
upload(req, res, function (err) {
if (err) {
// your error handling goes here
}
});
});
To find more details, multer documentation
This is what i did for handling errors:
I have created a file s3.js, which includes multer-s3 configuration and error handler
import S3 from 'aws-sdk/clients/s3.js'
import multer from 'multer'
import multerS3 from 'multer-s3'
import dotenv from 'dotenv'
dotenv.config()
const region = process.env.S3_REGION
const s3 = new S3({
region
})
// upload to S3 storage
export const uploadFiles = (req, res, next) => {
const upload = multer({
limits: { files: 6 },
storage: multerS3({
s3: s3,
bucket: process.env.S3_BUCKET_NAME,
metadata: function(req, file, cb) {
cb(null, { fieldName: file.fieldname })
},
key: function(req, file, cb) {
cb(null, `images/users/${ req.userId }/products/${ req.body.name }/${ new Date().toISOString() }-${ file.originalname }`)
},
})
}).array('photos', 6)
// Custom error handling for multer
upload(req, res, (error) => {
if (error instanceof multer.MulterError)
return res.status(400).json({
message: 'Upload unsuccessful',
errorMessage: error.message,
errorCode: error.code
})
if (error)
return res.status(500).json({
message: 'Error occured',
errorMessage: error.message
})
console.log('Upload successful.')
next()
})
}
You can now use this on the route that you want to upload files to.
import express from 'express'
import { uploadFiles } from '../config/s3.js'
const router = express.Router()
router.post('/upload', uploadFiles, async(req, res) => {
console.log(req.files)
})
export default router
Because I set the file limit to 6 I will get the following response when I try to send more than 6 files.

Resources