Steps
- Save uploaded images to server
- Model > route > controller
- Create media context
- On each upload response, update media context
- Show uploaded image as selected file with preview in
new.js
Server
// models/media
import mongoose from "mongoose";
const { ObjectId } = mongoose.Schema;
const mediaSchema = new mongoose.Schema(
{
url: String,
public_id: String,
postedBy: {
type: ObjectId,
ref: "User",
},
},
{ timestamps: true }
);
export default mongoose.model("Media", mediaSchema);
// routes/media
router.post(
"/upload-image-file",
formidable(),
requireSignin,
isAdmin,
uploadImageFile
);
// controllers/post
export const uploadImageFile = async (req, res) => {
// console.log(req.files); // [] of File {}
try {
// console.log(req.body.image);
const result = await cloudinary.uploader.upload(req.files.file.path);
// console.log("uploaded image url => ", result);
// save to db
const media = await new Media({
url: result.secure_url,
public_id: result.public_id,
postedBy: req.user._id,
}).save();
res.json(media);
// res.json({
// url: result.secure_url,
// public_id: result.public_id,
// });
} catch (err) {
console.log(err);
}
};
Client
import React from "react";
import { useState, createContext } from "react";
const MediaContext = createContext();
const MediaProvider = ({ children }) => {
const [media, setMedia] = useState({
images: [],
selected: null,
});
return (
<MediaContext.Provider value={[media, setMedia]}>
{children}
</MediaContext.Provider>
);
};
export { MediaContext, MediaProvider };
// add this line of code in props={} in
// UploadFile.js <Upload {...props} />
// MediaLibrary.js <Dragger {...props}>
setMedia({
images: [...media.images, info.file.response],
selected: info.file.response,
});
Then in new.js
show uploaded/selected file preview. Also send it to server on post create.
// pages/admin/posts/new.js
{media.selected && (
<>
<div style={{ marginBottom: 15 }}></div>
<Image width="100%" src={media.selected.url} />
</>
)}
Update post create controller function
// controllers/post
export const createPost = async (req, res) => {
try {
const { title, content, categories } = req.body;
// check if title is taken
const alreadyExist = await Post.findOne({
slug: slugify(title.toLowerCase()),
}).exec();
if (alreadyExist) return res.json({ error: "Title is taken" });
// get category ids based on category name
let ids = [];
for (let i = 0; i < categories.length; i++) {
Category.findOne({ name: categories[i] }).exec((err, c) => {
if (err) {
console.log(err);
}
// console.log("c", c._id);
ids.push(c._id);
});
}
// save post
setTimeout(async () => {
const newPost = await new Post({
...req.body,
slug: slugify(title),
categories: ids,
postedBy: req.user._id,
}).save();
return res.json(newPost);
}, 1000);
} catch (err) {
console.log(err);
}
};