I am trying to create MERN stack app with the function creating job posts with json data (company name, position etc) and the image (company logo).
I use multer and cloudinary to upload and save image, and mongo db to save file path. I cannot send POST request on POSTMAN with json data and image file at the same time, so I cannot test if my code actually works. Could someone verify it or help me how to send json and file at the same time?
Job.js in models
const mongoose = require('mongoose');
const slugify = require('slugify');
const JobSchema = new mongoose.Schema({
company: {
type: String,
required: [true, 'Please add a company'],
trim: true,
maxlength: [50, 'Company name can not be more than 50 characters'],
},
slug: String,
logo: {
type: String,
required: [true, 'Please add a logo'],
},
new: {
type: Boolean,
default: false,
},
featured: {
type: Boolean,
default: false,
},
position: {
type: String,
required: [true, 'Please add a position'],
maxlength: [100, '`Position` can not be more than 50 characters'],
},
role: {
type: String,
required: true,
enum: ['Frontend', 'Fullstack', 'Backend'],
},
level: {
type: String,
required: true,
enum: ['Junior', 'Midweight', 'Senior'],
},
postedAt: {
type: String,
required: true,
// need to be "-d ago"
// type: Date,
// default: Date.now,
},
contract: {
type: String,
required: true,
enum: ['Full Time', 'Part Time', 'Contract'],
},
location: { type: String, required: [true, 'Please add a location'] },
languages: { type: [String], required: [true, 'Please add languages'] },
tools: { type: [String], required: false },
createdAt: {
type: Date,
default: Date.now,
},
});
// Create job slug from the company name
JobSchema.pre('save', function (next) {
this.slug = slugify(this.company, { lower: true });
next();
});
module.exports = mongoose.model('Job', JobSchema);
jobs.js in controllers
const ErrorResponse = require('../utils/errorResponse');
const asyncHandler = require('../middleware/async');
const Job = require('../models/Job');
// @desc Create single job
// @routes POST /api/jobs
// @access Private
exports.createJob = asyncHandler(async (req, res, next) => {
const job = await Job.create({ ...req.body, logo: req.file.path });
res.status(201).json({
success: true,
data: job,
});
});
jobs.js in routes*
const express = require('express');
const parser = require('../middleware/cloudinary');
const {
getJobs,
getJob,
createJob,
updateJob,
deleteJob,
} = require('../controllers/jobs');
const router = express.Router();
router.route('/').get(getJobs).post(parser.single('logo'), createJob);
router.route('/:id').get(getJob).put(updateJob).delete(deleteJob);
module.exports = router;
server.js
const path = require('path');
const express = require('express');
const dotenv = require('dotenv');
const morgan = require('morgan');
const errorHandler = require('./middleware/error');
const connectDB = require('./config/db');
// Load env vars
dotenv.config({ path: './config/config.env' });
// Connect to database
connectDB();
// Route file
const jobRoutes = require('./routes/jobs');
// express app
const app = express();
// Body parser
app.use(express.json());
// Dev logging middleware
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
// routes
app.use('/api/jobs', jobRoutes);
app.use(errorHandler);
// listen for requests
const PORT = process.env.PORT || 5000;
const server = app.listen(
PORT,
console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`)
);
// Handle unhandled promise rejections
process.on('unhandledRejection', (err, promise) => {
console.log(`Error: ${err.message}`);
// Close server & exit process
server.close(() => process.exit(1));
});
cloudinary.js in middleware
const multer = require('multer');
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
const { CLOUDINARY_HOST, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET } =
process.env;
cloudinary.config({
cloud_name: CLOUDINARY_HOST,
api_key: CLOUDINARY_API_KEY,
api_secret: CLOUDINARY_API_SECRET,
});
const storage = new CloudinaryStorage({
cloudinary: cloudinary,
params: {
folder: 'folder name',
format: async (req, file) => 'svg',
public_id: (req, file) => file.filename,
},
});
const parser = multer({ storage: storage });
module.exports = parser;