I'm trying To render Image but it shows that Not allowed to load local resource:
Here's My code:
fileUpload.js
const multer = require("multer");
const path = require("path");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.resolve("./public/upload"));
},
filename: function (req, file, cb) {
const fileName = `${Date.now()}-${file.originalname}`;
cb(null, fileName);
},
});
module.exports = { storage };
postsController.js
exports.createPost = asyncHandler(async (req, res) => {
try {
const userFound = await User.findById(req.userAuth._id);
if (!userFound) {
throw new Error("User Not found");
}
const { title, content, categoryId } = req.body;
const postFound = await Post.findOne({ title });
if (postFound) {
throw new Error("Post already exists");
}
const post = await Post.create({
title,
content,
category: categoryId,
author: req?.userAuth?._id,
image: req?.file?.path,
});
console.log('This is Image Path req file',req.file.path);// Log this Whole Path:- C:\Users\rahul\Desktop\Github Final Project\backend\public\upload\1710572384640-solid black.jpg
await User.findByIdAndUpdate(
req?.userAuth?._id,
{
$push: { posts: post._id },
},
{
new: true,
}
);
await Category.findByIdAndUpdate(
req?.userAuth?._id,
{
$push: { posts: post._id },
},
{
new: true,
}
);
res.json({
status: "success",
message: "Post Successfully created",
post,
});
} catch (error) {
console.log("Final Error From controller", error);
res.status(400).json({
status: "error",
message: error.message,
});
}
});
postRouter.js
postsRouter.post("/", isLoggin, upload.single("file"), createPost);
userPosts.js
<div className="flex flex-wrap mb-12 -mx-4 md:mb-20">
{posts?.map((post) => {
return (
<>
<div className="w-full px-4 mb-8 md:w-1/2">
<a className="block mb-6 overflow-hidden rounded-md" href="#">
<img
className="w-full"
src={`./public/upload/${post?.image}`}
alt={post?.tile}
/>
</a>
<div className="mb-4">
<a
className="inline-block px-3 py-1 text-xs font-medium leading-5 text-green-500 uppercase bg-green-100 rounded-full shadow-sm hover:text-green-600 hover:bg-green-200"
href="#"
>
{post?.category?.name}
</a>
{/* Schedule post link */}
<Link
to={`/posts/schedule/${post?._id}`}
className="flex w-1/2 items-center px-6 py-1 bg-blue-500 text-white rounded-md shadow-md hover:bg-blue-700 transition-colors duration-300 ease-in-out"
>
<FiCalendar className="mr-2" /> Schedule Post
</Link>
</div>
<p className="mb-2 font-medium text-coolGray-500">
{new Date(post?.createdAt).toDateString()}
</p>
<a
className="inline-block mb-4 text-2xl font-bold leading-tight md:text-3xl text-coolGray-800 hover:text-coolGray-900 hover:underline"
href="#"
>
{post?.title}
</a>
<p className="mb-6 text-lg font-medium text-coolGray-500">
{post?.content}
</p>
</div>
</>
);
})}
</div>
Project Structure Backend Frontend
So Why My image is not Rendering and render through whole
I also servers from static content app.use(express.static(path.join(__dirname, "public"))); but still image is not render.
I also try to render Image from api like this but still its not working.
<img
className="w-full"
src={`http://localhost:9080/api/v1/posts/${post?.image}`}
alt={post?.tile}
/>
The problem is in the way you provide file destination folder in the multer's
destinationmethod: you're using absolute, instead of a path relative to your project folder, here:which then gets saved like that, and then the frontend tries to load it from the file system, and you get the error.
So, try changing the code to use path relative to the project folder in the
destinationmethod:Image path should now read
public\upload\1710572384640-solid black.jpgso, change the
srcin the template attribute to use just the path from the database:However, that will not show, because here:
it mounts
publicfolder on/path, so the path to image is actuallyupload\1710572384640-solid black.jpgSo, you can remove
publicpart from image path string, for example something like this:But it would be better to refactor the repository, and move upload folder from public folder, as a separate folder, to avoid mixing with public and better handling, and then you can either make it public (or create a separate route, add auth middleware etc.)
For example, you could make
uploada separate folder, and mount it on a path matching file destinatnio:Or also save and then use only filename to serve the file from now public upload folder (without
uploadpart in path):