I have to create a route that uploads 1 audio file and 1 image (resized) to Cloudinary using Multer Storage Cloudinary, and save the url and name in my mongo database.
I get the error "Invalid image file" when I try to upload the audio file (even if I delete transformation and add "mp3" in allowedFormats.
Cloudinary code:
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_KEY,
api_secret: process.env.CLOUDINARY_SECRET
});
const storage = new CloudinaryStorage({
cloudinary,
params: {
folder: 'nono',
// transformation: [
// {width: 500, height: 500, crop: "fill"}
// // ],
// allowedFormats: ['jpeg', 'png', 'jpg', 'mp3']
}
});
module.exports = { cloudinary, storage }
Route code:
router.route("/")
.get(catchAsync(sounds.index));
.post(isLoggedIn, upload.fields([{ name: 'sound[audio]', maxCount: 1 }, { name: 'sound[image]', maxCount: 1 }]), joiValidationSounds, catchAsync(sounds.newSound));
module.exports.newSound = async (req, res) => {
const sound = new Sound(req.body.sound);
console.log(req.files)
sound.image.url = req.files["sound[image]"][0].path;
sound.image.filename = req.files["sound[image]"][0].filename;
sound.audio.url = req.files["sound[audio]"][0].path;
sound.audio.filename = req.files["sound[audio]"][0].filename;
sound.author = req.user._id;
await sound.save();
req.flash("success", "Se ha añadido un nuevo sonido.");
res.redirect(`/sounds/categories/:category/${sound._id}`);
}
Form code:
<form action="/sounds" method="POST" novalidate enctype="multipart/form-data">
<div >
<label for="audio" >Audio:</label>
<div >
<input type="file" name="sound[audio]" id="audio">
</div>
</div>
<div >
<label for="image" >Imagen:</label>
<div >
<input type="file" name="sound[image]" id="image">
</div>
</div>
<button type="submit" >Crear</button>
<button type="reset" >Limpiar</button>
</form>
I can upload 2 images instead without problems. I also checked that Cloudinary supports mp3 files.
EDIT: I managed to upload the audio with resource_type: 'video', allowedFormats: ['mp3'], and 2 different storages.
But now I get the error "Unexpected field" when I try to upload both.
New code:
const storageAudio = new CloudinaryStorage({
cloudinary: cloudinary,
params: {
folder: 'nono',
format: 'mp3',
resource_type: 'video',
allowedFormats: ['mp3'],
}
});
const storageImage = new CloudinaryStorage({
cloudinary: cloudinary,
params: {
folder: 'nono',
transformation: [
{width: 500, height: 500, crop: "fill"}
],
format: 'jpg',
resource_type: 'image',
allowedFormats: ['jpeg', 'png', 'jpg']
}
});
module.exports = { cloudinary, storageImage, storageAudio };
const multer = require("multer");
const { storageImage, storageAudio } = require("../cloudinary");
const uploadAudio = multer({ storage: storageAudio });
const uploadImage = multer({ storage: storageImage });
router.route("/")
.get(catchAsync(sounds.index))
.post(isLoggedIn,
// uploadAudio.fields([{ name: 'sound[audio]', maxCount: 1 }]), uploadImage.fields([{ name: 'sound[image]', maxCount: 1 }]),
uploadAudio.single("sound[audio]"),
uploadImage.single("sound[image]"),
// upload.fields([{ name: 'sound[audio]', maxCount: 1 }, { name: 'sound[image]', maxCount: 1 }]),
joiValidationSounds, catchAsync(sounds.newSound)
);
CodePudding user response:
When uploading files to Cloudinary, one of the upload parameters is the resource_type, telling Cloudinary how to process the incoming file. The possible values are 'image', 'video', 'raw' (non-image, non-video), or 'auto' (where the file will be opened after upload to check the type)
If you're getting the Invalid image file error when uploading a video, most likely it means that the resource_type on the upload call was set to 'image', and looking at the repo of the plugin you're using, that appears to be the case: https://github.com/affanshahid/multer-storage-cloudinary/issues/13
You may need to contact the plugin maintainer and see if they can allow overriding the resource type in a future release, or fork the plugin to allow the resource type to be overridden in the configuration
Alternatively, you can use Cloudinary's SDK directly to perform the upload, and use multer just to make the uploaded file available to your code. In which case the Cloudinary SDK uses resource_type "auto" by default when uploading, and you can override the value in your own code if needed
CodePudding user response:
Finally, I found a solution (with one storage and one form) to upload both image and audio:
1)Set the params to resource_type: 'auto', and allowedFormats to all the formats you will upload.
const storage = new CloudinaryStorage({
cloudinary,
params: {
folder: 'nono',
resource_type: 'auto',
allowedFormats: ['jpeg', 'png', 'jpg', 'mp3'],
transformation: [
{width: 500, height: 500, crop: "fill"}
]
}
});
2)Use upload.fields
upload.fields([{ name: 'sound[audio]', maxCount: 1 }, { name: 'sound[image]', maxCount: 1 }]),
