Reputation: 1774
I am trying to send a file to api in a next js app. The image will be uploaded to cloudinary:
Function calling api is:
async uploadButtonClicked(imageUpload) {
const formData = new FormData();
//formData.append('test', "testing");
formData.append('postPic', imageUpload.files[0]);
const res = await fetch('/api/hello', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
},
body: formData,
})
console.log(imageUpload.files[0])
in front end gives me the values below and looks good.
In the api,
export default (upload.single('postPic'), async (req, res) => {
console.log(req.body)
The above is undefined
when I use
export const config = {
api: {
bodyParser: false,
},
};
When I remove the bodyParser setting (bodyParser is true), the data is as a stream which is not useful for upload. I get a upload error as shown below:
Cloudinary will upload if the body reaches the api in this format below:
What should be changed to get the body (which is basically an image file) to reach the api in the proper format as shown above?
I think the question can also be asked as: Why is the req.body undefined
when using bodyParser: false
?
Upvotes: 4
Views: 20930
Reputation: 129
This works for me
import cloudinary from 'cloudinary';
import formidable from 'formidable';
cloudinary.config({
cloud_name: '',
api_key: '',
api_secret: ''
});
export const config = {
api: {
bodyParser: false,
},
}
export default async (req, res) => {
const form = new formidable.IncomingForm();
form.uploadDir = "./";
form.keepExtensions = true;
await form.parse(req, (err, fields, files) => {
cloudinary.v2.uploader.upload(files.image.path, function(error, result) {
res.status(200).json({
success: true,
data: result.secure_url
})
});
});
}
Upvotes: 0
Reputation: 111
I ran into the same error but Formidable worked for me. Try putting the image into Form Data first.
From Client:
export const uploadImage = async (image) => {
const formData = new FormData();
formData.append('image', image);
const response = await axios.post('/api/v1/image', formData);
return response.data;
}
And below is on server API : /api/v1/image
import formidable from 'formidable';
export const config = {
api: {
bodyParser: false,
},
}
export default async (req, res) => {
const form = new formidable.IncomingForm();
form.uploadDir = "./";
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
console.log(err, fields, files);
});
};
Upvotes: 6
Reputation: 1041
If you're uploading to Cloudinary, why are you trying to send the file from the client to your nextjs api? You can upload directly to Cloudinary.
With a library like react-uploady. It's as simple as this:
import React from "react";
import Uploady from "@rpldy/uploady";
import UploadButton from "@rpldy/upload-button";
const CLOUD_NAME = "<your-cloud-name>";
const UPLOAD_PRESET = "<your-upload-preset>";
const App = () => (<Uploady
destination={{
url: `https://api.cloudinary.com/v1_1/${CLOUD_NAME}/upload`,
params: {
upload_preset: UPLOAD_PRESET,
}
}}>
<UploadButton/>
</Uploady>);
Upvotes: 0