I can't upload an image using ESM for cloudinary - javascript

I have a problem in this part of my code,with COMMONJS and it's working, my question is how can I make it work on ESM,
I've tried this but not workiing :
import express from 'express';
const router = express.Router();
import cloudinary from 'cloudinary';
import { unlinkSync } from 'node:fs';
const router = require('express').Router();
const cloudinary = require('cloudinary');
const { unlinkSync } = require('node:fs');
// we will upload image on cloudinary
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
// Upload image only admin can use
router.post('/upload', (req, res) => {
try {
cloudinary.v2.uploader.upload(file.tempFilePath, { folder: 'test' }, async (err, result) => {
if (err) throw err;
removeTmp(file.tempFilePath);
res.json({ public_id: result.public_id, url: result.secure_url });
});
} catch (err) {
return res.status(500).json({ msg: err.message });
}
});
const removeTmp = (path) => {
unlinkSync(path, err => {
if(err) console.log('this is the error',err);;
});
console.log(`successfully deleted ${path}`);
};
module.exports = router;

Try this one :
import express from 'express';
import multer from 'multer';
import { v2 as cloudinary } from 'cloudinary';
import streamifier from 'streamifier';
import { isAdmin, isAuth } from '../utils.js';
const upload = multer();
const uploadRouter = express.Router();
uploadRouter.post(
'/',
isAuth,
isAdmin,
upload.single('file'),
async (req, res) => {
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const streamUpload = (req) => {
return new Promise((resolve, reject) => {
const stream = cloudinary.uploader.upload_stream((error, result) => {
if (result) {
resolve(result);
} else {
reject(error);
}
});
streamifier.createReadStream(req.file.buffer).pipe(stream);
});
};
const result = await streamUpload(req);
res.send(result);
}
);
export default uploadRouter;

Related

file upload multier MulterError: Unexpected field

Not able to upload image in MongoDB database using NodeJS
Middleware fieldName and key name is also same still not working. no solution on internet
server.js
import cookieParser from "cookie-parser";
import multer from "multer";
export const app = express();
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
let upload = multer()
app.use(upload.array())
app.use("/",routLog,router)
app.listen(process.env.PORT,()=>{
db()
console.log(`Server is Runing on http://localhost:${process.env.PORT}`)
})
blogroute.js
import { fileUploder } from "../middelware/fileUploder.js";
export const blogRouter = Router()
blogRouter.post('/:user/create-post', fileUploder.single("file"), blogsController.createPos
This middleware file fileUplad.js which is use to store in upload folder and then from that will store in MongoDB in buffer ferment
import { randomBytes } from "crypto";
import multer from "multer";
import path from "path";
const storage = multer.diskStorage({
destination: './upload',
filename: async (req, file, callback) => {
return await randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "upload"
};
resolve(fileInfo);
})
}
})
export const fileUploder = multer({
storage: storage,
limits: { fileSize: 2000 },
fileFilter: (req, file, callback) => {
allowedFileTypes = /jpeg|jpg|png|gif/;
if (file.mimetype == 'jpg' || file.mimetype == 'jpeg' || file.mimetype == 'png', file.mimetype == 'gif') {
return cb(null, true);
} else {
cb("Invalid file type. Only JPEG, PNG and GIF file are allowed.")
}
}
})
MulterError: Unexpected field
at wrappedFileFilter (/mnt/ssd/BlogProject/backendapi/node_modules/multer/index.js:40:19)
at Multipart.<anonymous> (/mnt/ssd/BlogProject/backendapi/node_modules/multer/lib/make-middleware.js:107:7)
at Multipart.emit (node:events:527:28)
at HeaderParser.cb (/mnt/ssd/BlogProject/backendapi/node_modules/busboy/lib/types/multipart.js:358:14)
at HeaderParser.push (/mnt/ssd/BlogProject/backendapi/node_modules/busboy/lib/types/multipart.js:162:20)
at SBMH.ssCb [as _cb] (/mnt/ssd/BlogProject/backendapi/node_modules/busboy/lib/types/multipart.js:394:37)
at feed (/mnt/ssd/BlogProject/backendapi/node_modules/streamsearch/lib/sbmh.js:248:10)
at SBMH.push (/mnt/ssd/BlogProject/backendapi/node_modules/streamsearch/lib/sbmh.js:104:16)
at Multipart._write (/mnt/ssd/BlogProject/backendapi/node_modules/busboy/lib/types/multipart.js:567:19)
at writeOrBuffer (node:internal/streams/writable:389:12)```
This is simple example :
let multer = require('multer');
let multerImage = multer().single('file');
function uploadAvatar(req, res) {
let phone = data.phoneNumber;
multerImage(req, res, () => {
let file = req.file;
if (isUndefined(file))
return Json.builder(Response.HTTP_BAD_REQUEST);
let {
fileUrl
} = File.validationAndWriteFile(file.buffer, Util.getFileFormat(file.originalname));
Update.img(phone, fileUrl, result => {
if (!result)
return Json.builder(Response.HTTP_BAD_REQUEST);
Json.builder(Response.HTTP_OK);
});
});
}

uploading two files from two fields with multer as middleware

i'm trying to upload two files with different file extensions with multer from two fields but when i try it with postman the result always for the file is null, what is the solution for my problem? here is my code
middleware/uploadEpub
const multer = require('multer')
exports.uploadEpub = (epubFile, coverFile) => {
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads")
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' + file.originalname.replace(/\s/g, ""))
}
})
const upload = multer({
storage
}).fields([{name: "bookFile", maxCount: 1},{name: "coverFile", maxCount: 1}])
}
controller/book
exports.addBook = async (req, res) => {
try {
const { ...data } = req.body
const newBook = await book.create({
...data,
bookFile: req.file,
coverFile: req.file
})
let bookData = await book.findOne({
where: {
id: newBook.id
},
attributes:{
exclude: ['createdAt','updatedAt']
}
})
bookData = JSON.parse(JSON.stringify(bookData))
res.send({
status: "Success",
Book: {
...bookData
}
})
} catch (error) {
console.log(error)
res.status(500).send({
status: "Failed",
message: "Server Error"
})
}
}
Multer set up
const multer = require('multer')
const path = require('path')
const { nanoid } = require('nanoid')
//Set Storage Engine
const storage = multer.diskStorage({
destination: './public/uploads/',
filename: (req, file, callback) => {
const id = nanoid(6)
const newFilename = `${file.fieldname}_${id}-${new Date().toISOString().replace(/:/g, '-')}${path.extname(file.originalname)}`
callback(null, newFilename)
}
})
const upload = multer({
storage: storage,
limits: { fileSize: 5572864 }, // up to 5.5 MB
fileFilter: (req, file, callback) => {
checkFileType(file, callback)
},
})
//Check File Type
const checkFileType = (file, cb) => {
//Allowed extensions
const fileType = /jpeg|jpg|png|gif|svg|pdf|epub/
//Check extension
const extname = fileType.test(path.extname(file.originalname).toLowerCase())
//Check mimetype
const mimetype = fileType.test(file.mimetype)
if (extname && mimetype) {
return cb(null, true)
} else {
return cb('Error: wrong file type!')
}
}
module.exports = upload
/***** middlewares.js *****/
module.exports.imageUploader = (req, res, next)=>{
const files = req.files
const uploadedFiles = []
for (var i = 0; i <images.length; i++){
uploadFiles.push('https://yourserver.com/public/uploads/' + files[i].filename)
}
req.uploadFiles = uploadFiles.toString() //appending files to req
next()
return
}
/**** index.js or app.js ****/ //where your routes are defined
router.post('/books/add', upload.array('images', 10), imageUploader, book.addBook) // allowing up to 10 files to be uploaded, calling imageUploader as a middleware
/*** Controllers/book ***/
exports.addBook = async (req, res) => {
const uploadedFiles = req.uploadFiles; //catching files from imageUploader middleware
// ... rest of your code
}
Try to upload the file as form-data in postman, and put the key with the same name that you have set in multer, the postman will look like this:
Try this:
const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
})

Refactored AWS S3 Uploader to reusable code doesn't invoke uploader

Consider the Controller :
authControoler:
const mongoose = require('mongoose');
const User = mongoose.model("User");
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { JWT_SECRET } = require('../config/keys');
const AWS = require('aws-sdk');
const multer = require("multer");
const multerS3 = require("multer-s3");
const uuid = require('uuid');
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
region: process.env.AWS_REGION,
});
const uuid_name = uuid.v4();
const signUpUploader = multer({
storage: multerS3({
s3: s3,
bucket: process.env.AWS_S3_BUCKET_NAME,
metadata: function (req, file, cb) {
console.log("Uploading file to S3...");
cb(null, {
OriginalFileName: file.originalname.toLowerCase(),
RandomName: uuid_name,
});
},
key: function (req, file, cb) {
cb(null, file.originalname);
}
})
}).single('singleFile');
exports.signUp = async (req, res, next) => {
// call the uploader to AWS S3
signUpUploader(req, res, function (err) {
if (err) {
// An error occurred when uploading
console.log('Something went wrong :', err);
return;
}
// Everything went fine
console.log('Everything went fine');
const image_s3_url = req.file.location;
const { name, email, password } = req.body;
if (!email || !password || !name) {
return res.status(422).json({ error: "please add all the fields" })
}
// update User in Mongo ...
});
};
I've refactored the code into reusable aws code , as follows :
aws.js:
const AWS = require('aws-sdk');
const multer = require("multer");
const multerS3 = require("multer-s3");
const uuid = require('uuid');
const uuid_name = uuid.v4();
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
region: process.env.AWS_REGION,
});
module.exports = class AWSUtils {
constructor(filePropertyName) {
this.filePropertyName = filePropertyName;
}
getFilePropertyName() {
return this.filePropertyName;
}
uploadImage() {
const signUpUploader = multer({
storage: multerS3({
s3: s3,
bucket: process.env.AWS_S3_BUCKET_NAME,
metadata: function (req, file, cb) {
console.log("Uploading file to S3...");
cb(null, {
OriginalFileName: file.originalname.toLowerCase(),
RandomName: uuid_name,
});
},
key: function (req, file, cb) {
cb(null, file.originalname);
}
})
}).single(this.filePropertyName);
return signUpUploader;
}
}
authControoler:
const mongoose = require('mongoose');
const User = mongoose.model("User");
const crypto = require('crypto');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { JWT_SECRET } = require('../config/keys');
const AWSUtils = require('../utils/aws');
const _utils = new AWSUtils('singleFile');
exports.signUp = async (req, res, next) => {
console.log('In signUp');
// call the uploader to AWS S3
_utils.uploadImage(req, res, function (err) { // Refactored !!!
if (err) {
// An error occurred when uploading
console.log('Something went wrong :', err);
return;
}
// Everything went fine
console.log('Everything went fine');
const image_s3_url = req.file.location;
const { name, email, password } = req.body;
if (!email || !password || !name) {
return res.status(422).json({ error: "please add all the fields" })
}
// update User in Mongo ...
});
};
After refactored and extracted out the AWS code into its own file (aws.js) , I call uploadImage however nothing happens , no error , no upload , nothing.
What am I missing here ?
multer returns an Express middleware function. In the original code, that middleware function was assigned directly to signUpUploader
In your refactored code, the _util.uploadImage function is actually returning the middleware function, but in your code, you're not using the result as middleware, instead trying to use _util.uploadImage.
There are a few options, but a quick fix would be to do something like this:
Replace:
_utils.uploadImage(req, res, function (err) {
// The function body
})
With:
const signUpUploader = _utils.uploadImage();
signUpUploader(req, res, function (err) {
// The function body
})
That will use the mutler middleware the way you are expecting.

Why is the Query from getInitialProps empty?

I want to fetch some data using query parameters on the server for a page.
However, my query is empty inside getInitialProps when rendered through server. Why could this be happening?
Moreover, I have noticed this only happens in production server and not in the dev or prod env on my local.
Here's some code
import React from 'react';
import Config from 'component/Config';
import { withAuthSync } from 'util/auth';
import apiUrl from 'util/apiUrl';
function ResourceConfigPage({ data }) {
return <Config data={data} />;
}
ResourceConfigPage.getInitialProps = async ctx => {
const { resourceId } = ctx.query;
try {
const response = await fetch(`${apiUrl}/resource/config?resourceId=${resourceId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
const data = await response.json();
return { data };
}
}
return {};
};
export default withAuthSync(ResourceConfigPage);
My next app uses a custom express server and here's how it looks.
const express = require('express');
const next = require('next');
const compression = require('compression');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
app.setAssetPrefix(dev ? '' : 'https://example.com');
server.use(compression());
server.get('/healthcheck', (req, res) => {
res.status(200).json({});
});
server.get('/', (req, res) => {
if (req.cookies.sessionId) {
res.redirect('/dashboard');
}
res.redirect('/login');
});
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, err => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});

Nodejs App works locally but only two route is working on Heroku

Hello all first and foremost this issue may seem like a duplicate but it is not as I have gone through other SO post relating to mine but it still didnt help and hence the reason I am making another. Please I need help, I have a nodejs back-end that is working locally without any issue. I uploaded it to heroku and now only two routes is working. All other routes are not working. I am able register, login and add new users.
This is for my add users routes that is working both locally and on heroku.
import mongoose from 'mongoose';
import { Router } from 'express';
import bodyParser from 'body-parser';
import User from '../model/user';
import { authenticate } from '../middleware/authMiddleware';
export default({ config, db }) => {
let api = Router();
// '/v1/user/add' - Create
api.post('/add', authenticate, (req, res) => {
let newUser = new User();
newUser.username = req.body.username;
newUser.email = req.body.email;
newUser.phonenumber = req.body.phonenumber;
newUser.profilepicurlicUrl = req.body.profilepicurl;
newUser.save(err => {
if (err) {
res.status(500).json({ message: err });
return;
}
res.status(200).json(newUser);
});
});
This is for my register user and login user that is working both locally and on heroku
import mongoose from 'mongoose';
import { Router } from 'express';
import bodyParser from 'body-parser';
import passport from 'passport';
import config from '../config';
import Account from '../model/account';
import UserDataExt from './extensions/userData-ext';
import async from 'async';
import crypto from 'crypto';
import { generateAccessToken, respond, authenticate } from '../middleware/authMiddleware';
var nodeMailer = require('nodemailer');
export default ({ config, db }) => {
let api = Router();
// '/v1/account/register'
api.post('/register', (req, res) => {
UserDataExt.findUserByEmail(req.body.email, (err, userData) => {
if (err) {
res.status(409).json({ message: `An error occured: ${err.message}`});
return;
} else if (userData) {
res.status(300).json({ message: `Email ${req.body.email} is already registered`});
}
// else {
Account.register(new Account({username: req.body.email}), req.body.password, function(err, account) {
if(err) {
res.status(500).json({ message: err });
return;
}
console.log("Registering new account");
passport.authenticate('local', { session: false })(req, res, () => {
res.status(200).send('Successfully created new account');
});
});
// }
});
});
// '/v1/account/login'
api.post('/login', (req, res, next) => {
UserDataExt.findUserByEmail(req.body.email, (err, userData) => {
if (err) {
res.status(409).json({ message: `An error occured: ${err.message}`});
return;
} else {
next();
}
});
}, passport.authenticate('local', { session: false, scope: [] }), (err, req, res, next) => {
if (err) {
res.status(401).json({ message: `Password is incorrect`});
return;
}
}, generateAccessToken, respond);
This is for my category route that is not working on heroku, but is working locally
import mongoose from 'mongoose';
import { Router } from 'express';
import Category from '../model/category';
import bodyParser from 'body-parser';
import { authenticate } from '../middleware/authMiddleware';
export default({ config, db }) => {
let api = Router();
// /v1/category/add Create
api.post('/add', authenticate, (req, res) => {
let newCategory = new Category();
newCategory.submittedById = req.body.submittedById;
newCategory.categoryTitle = req.body.categoryTitle;
newCategory.categoryDescription = req.body.categoryDescription;
newCategory.recommended = req.body.recommended;
newCategory.save(err => {
if (err) {
res.status(500).json({message: err});
return;
}
res.status(200).json({message: 'Category saved successfully'});
});
});
// /v1/category/ Read
api.get('/', authenticate, (req, res) => {
Category.find({}, (err, category) => {
if (err) {
res.status(500).json({message: `An erro has occured ${err.message}`});
return;
}
res.status(200).json(category);
});
});
This is my authenticate middleware code
import jwt from 'jsonwebtoken';
import expressJwt from 'express-jwt';
const TOKENTIME = 60*60*24*90;
const SECRET = "#######";
let authenticate = expressJwt({ secret: SECRET });
let generateAccessToken = (req, res, next) => {
req.token = req.token || {};
req.token = jwt.sign ({
id: req.user.id,
}, SECRET, {
expiresIn: TOKENTIME // 90 days
});
next();
}
let respond = (req, res) => {
res.status(200).json({
user: req.user.username,
token: req.token,
id: req.user._id
});
}
module.exports = {
authenticate,
generateAccessToken,
respond
}

Categories