Issues making multer file optional
Closed this issue · 1 comments
Hello, I'm having difficulty trying to make one of the files uploaded via multer optional. I'm using next-connect as a middleware.
`import { getSession } from "next-auth/react";
import Video from "../../../../../db/models/video";
import User from "../../../../../db/models/user";
import multer from "multer";
import path from "path";
import { createRouter, expressWrapper } from "next-connect";
import cloudinary from "cloudinary";
import DatauriParser from "datauri/parser";
const parser = new DatauriParser();
cloudinary.v2.config({
cloud_name: process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
export const config = {
api: {
bodyParser: false,
},
};
const storage = multer.memoryStorage();
const upload = multer({
storage: storage,
limits: {
fieldSize: 28000000,
},
});
const router = createRouter();
router
.use(
expressWrapper(
upload.fields([{ name: "image", maxCount: 1 }, { name: "video" }]) // want to make video optional
)
)
.post(async (req, res) => {
const session = await getSession({ req });
if (!session) return res.status(400).json({ message: "Not Authorised!" });
const {
title,
description,
} = req.body;
const image = req.files["image"][0];
const video = req.files["video"][0];
if (!title || !description) {
return res.status(400).json({ message: "Fill in all fields" });
}
if (image === undefined) {
return res.status(400).json({ message: "Fill in image field" });
}
if (image.fieldname !== "image") {
return res.status(400).json({ message: "File must be of image" });
}
if (image.size > 5000000) {
return res
.status(400)
.json({ message: "Image size must be less than 5MB" });
}
try {
if (req.method === "POST") {
const userid = session?.user?.id;
const user = await User.findOne({
where: { id: userid },
});
if (!user)
return res.status(400).json({ message: "User does not exist!." });
const formatImageTo64 = (file) =>
parser.format(
path.extname(file.originalname).toString(),
file.buffer
);
const cloudinaryImageUpload = (file) =>
cloudinary.uploader.upload(file);
const image64 = formatImageTo64(image);
const uploadImageResult = await cloudinaryImageUpload(image64.content);
if (typeof video === "object") {
if (video.fieldname !== "video") {
return res.status(400).json({ message: "File must be of video" });
}
if (video.size > 28000000) {
return res
.status(400)
.json({ message: "Video size must be less than 28MB" });
}
const formatVideoTo64 = (file) =>
parser.format(
path.extname(file.originalname).toString(),
file.buffer
);
const cloudinaryVideoUpload = (file) =>
cloudinary.v2.uploader.upload(file, { resource_type: "video" });
const video64 = formatVideoTo64(video);
const uploadVideoResult = video
? await cloudinaryVideoUpload(video64.content)
: null;
const userId = user?.id;
const newVideo = await Video.create(
{
title,
image: uploadImageResult.url,
video: uploadVideoResult.url,
video_id: uploadVideoResult.public_id,
video_signature: uploadVideoResult.signature,
description,
image_id: uploadImageResult.public_id,
image_signature: uploadImageResult.signature,
user_id: userId
} );
if (!newVideo)
return res.status(400).json({ message: "Can't add new video" });
res.status(200).json({
message: "Video was successfully created",
newVideo,
});
} else {
const userId = user?.id;
const newVideo = await Video.create(
{
title,
image: uploadImageResult.url,
description,
image_id: uploadImageResult.public_id,
image_signature: uploadImageResult.signature,
user_id: userId
},
);
if (!newVideo)
return res.status(400).json({ message: "Can't add new video" });
return res.status(200).json({
message: "Video was successfully created",
newVideo,
});
}
} else {
res.status(500).json({ message: "HTTP method not valid" });
}
} catch (err) {
return res.status(500).json({
message: "Internal error",
err,
});
} });
export default router.handler({
onError: (err, req, res) => {
console.error(err.stack);
res.status(500).json({ message: Fill in video/image field
});
},
onNoMatch: (req, res) => {
res.status(404).json({ message: "Page is not found" });
},
});
`
I have no issues when I upload both image and video together but anytime I upload only the image, I get an error which says "Fill in video/image field"
This is how I solved it.
const video = (req.files["video"] || [])[0];
instead of
const video = req.files["video"][0];
So this is my full code:
`
import { getSession } from "next-auth/react";
import Video from "../../../../../db/models/video";
import User from "../../../../../db/models/user";
import multer from "multer";
import path from "path";
import { createRouter, expressWrapper } from "next-connect";
import cloudinary from "cloudinary";
import DatauriParser from "datauri/parser";
const parser = new DatauriParser();
cloudinary.v2.config({
cloud_name: process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
export const config = {
api: {
bodyParser: false,
},
};
const storage = multer.memoryStorage();
const upload = multer({
storage: storage,
limits: {
fieldSize: 28000000,
},
});
const router = createRouter();
router
.use(
expressWrapper(
upload.fields([{ name: "image", maxCount: 1 }, { name: "video", maxCount: 1 }]) // want to make video optional
)
)
.post(async (req, res) => {
const session = await getSession({ req });
if (!session) return res.status(400).json({ message: "Not Authorised!" });
const {
title,
description,
} = req.body;
const image = req.files["image"][0];
const video = (req.files["video"] || [])[0];
if (!title || !description) {
return res.status(400).json({ message: "Fill in all fields" });
}
if (image === undefined) {
return res.status(400).json({ message: "Fill in image field" });
}
if (image.fieldname !== "image") {
return res.status(400).json({ message: "File must be of image" });
}
if (image.size > 5000000) {
return res
.status(400)
.json({ message: "Image size must be less than 5MB" });
}
try {
if (req.method === "POST") {
const userid = session?.user?.id;
const user = await User.findOne({
where: { id: userid },
});
if (!user)
return res.status(400).json({ message: "User does not exist!." });
const formatImageTo64 = (file) =>
parser.format(
path.extname(file.originalname).toString(),
file.buffer
);
const cloudinaryImageUpload = (file) =>
cloudinary.uploader.upload(file);
const image64 = formatImageTo64(image);
const uploadImageResult = await cloudinaryImageUpload(image64.content);
if (typeof video !== "undefined") {
if (video.fieldname !== "video") {
return res.status(400).json({ message: "File must be of video" });
}
if (video.size > 28000000) {
return res
.status(400)
.json({ message: "Video size must be less than 28MB" });
}
const formatVideoTo64 = (file) =>
parser.format(
path.extname(file.originalname).toString(),
file.buffer
);
const cloudinaryVideoUpload = (file) =>
cloudinary.v2.uploader.upload(file, { resource_type: "video" });
const video64 = formatVideoTo64(video);
const uploadVideoResult = video
? await cloudinaryVideoUpload(video64.content)
: null;
const userId = user?.id;
const newVideo = await Video.create(
{
title,
image: uploadImageResult.url,
video: uploadVideoResult.url,
video_id: uploadVideoResult.public_id,
video_signature: uploadVideoResult.signature,
description,
image_id: uploadImageResult.public_id,
image_signature: uploadImageResult.signature,
user_id: userId
} );
if (!newVideo)
return res.status(400).json({ message: "Can't add new video" });
res.status(200).json({
message: "Video was successfully created",
newVideo,
});
} else {
const userId = user?.id;
const newVideo = await Video.create(
{
title,
image: uploadImageResult.url,
description,
image_id: uploadImageResult.public_id,
image_signature: uploadImageResult.signature,
user_id: userId
},
);
if (!newVideo)
return res.status(400).json({ message: "Can't add new video" });
return res.status(200).json({
message: "Video was successfully created",
newVideo,
});
}
} else {
res.status(500).json({ message: "HTTP method not valid" });
}
} catch (err) {
return res.status(500).json({
message: "Internal error",
err,
});
} });
export default router.handler({
onError: (err, req, res) => {
console.error(err.stack);
res.status(500).json({ message: Fill in video/image field });
},
onNoMatch: (req, res) => {
res.status(404).json({ message: "Page is not found" });
},
});
`