Axios post isn't handling the response - node.js

I am uploading images to Cloudinary and want to retrieve the image url after it is uploaded. It is uploading correctly and I can console.log the url on server side but afterwards the response is not handled in the axios call on the client side and no error messages appear.
My client:
submitFile = () => {
var formData = new FormData();
formData.append('image', this.state.file, 'tmp_name');//this.state.file is not correct format compared to postman constructed
axios.post('http://localhost:3000/upload', formData).then(function(response) {
console.log(response);
});
}
My server:
server.post('/upload', async (req, res, next) => {
const upload = multer({ storage }).single('image')
upload(req, res, function(err) {
if (err) {
return res.send(err)
}
const path = req.file.path
cloudinary.uploader.upload(
path,
{ public_id: `${filename()}` },
async function(err, image) {
if (err) return res.send(err)
console.log('file uploaded to Cloudinary')
// remove file from server
const fs = require('fs')
fs.unlinkSync(path)
}
).then(result => {res.send(result)})
})
Again I want to just be able to view the response and save it but everything after then .then doesn't execute.

You need to remove bracket in then of server code
server.post('/upload', async (req, res, next) => {
/* upload code*/
).then(result => res.send(result))
})
OR
Add return in then of server code
server.post('/upload', async (req, res, next) => {
/*upload code*/
).then(result => { return res.send(result)})
})

Related

Saving Images React To Nodejs

I am trying to upload an image from my front end to the backend but it it doesn't send the image in the request
It says that the formdata is empty and it says that there's no image found, where is the problem and how can I fix this error?
Here is the code from the Frontend made in react:
const [userInfo, setuserInfo] = useState({
file:[],
filepreview:null,
});
const handleInputChange = (event) => {
setuserInfo({
...userInfo,
file:event.target.files[0],
filepreview:URL.createObjectURL(event.target.files[0]),
});
}
const [isSucces, setSuccess] = useState(null);
const submit = async () =>{
const formdata = new FormData();
formdata.append('avatar', userInfo.file);
console.log(formdata)
Axios.post("http://localhost:4000/imageupload", formdata,{
headers: { "Content-Type": "multipart/form-data" }
})
.then(res => { // then print response status
console.warn(res);
if(res.data.success === 1){
setSuccess("Image upload successfully");
}
})
}
The code of the Backend made in NodeJS:
const storage = multer.diskStorage({
destination: path.join(__dirname, './temp', 'uploads'),
filename: function (req, file, cb) {
// null as first argument means no error
cb(null, Date.now() + '-' + file.originalname )
}
})
app.post('/imageupload', async (req, res) => {
try {
// 'avatar' is the name of our file input field in the HTML form
let upload = multer({ storage: storage}).single('avatar');
upload(req, res, function(err) {
// req.file contains information of uploaded file
// req.body contains information of text fields
if (!req.file) {
return res.send('Please select an image to upload');
}
else if (err instanceof multer.MulterError) {
return res.send(err);
}
else if (err) {
return res.send(err);
}
const classifiedsadd = {
image: req.file.filename
};
res.send("ok")
});
}catch (err) {console.log(err)}
})
Edit:
Multer is essentially a nodejs router,i.e. a function that can be pipelined between your HTTP request and HTTP response.
I think that you should first make multer analyze your HTTP content and to actually populate the req.file before actually evaluate express parsers do their job.
const storage = multer.diskStorage({
destination: path.join(__dirname, './temp', 'uploads'),
filename: function (req, file, cb) {
// null as first argument means no error
cb(null, Date.now() + '-' + file.originalname )
}
})
let upload = multer({ storage: storage});
app.post('/imageupload', upload.single('avatar'), async (req, res) => {
try {
// 'avatar' is the name of our file input field in the HTML form
// req.file contains information of uploaded file
// req.body contains information of text fields
if (!req.file) {
return res.send('Please select an image to upload');
}
else if (err instanceof multer.MulterError) {
return res.send(err);
}
else if (err) {
return res.send(err);
}
const classifiedsadd = {
image: req.file.filename
};
res.send("ok")
}catch (err) {console.log(err)}
})
I am assuming that your upload code is working. Have you tried to read the HTTP request from your browser to see that the image has been correctly attached to the request?
Because probably the issue lies in the fact that you are not actually parsing the image.
const file = new File(userInfo.file, "avatar.png", {
type: 'image/png' // choose the appropriate
});
const formdata = new FormData();
formdata.append('avatar', file);
console.log(formdata)

How to get request extension in express?

How to understand if somebody requests image or file in express? For example:
https://example.com/image.png
https://example.com/file.js
app.get("/:fileName", (req, res) => {
const file = req.params.fileName.split(".");
const fileExtension = file[file.length-1];
const imageExtensions = ["png", "jpg"];
if(imageExtensions.includes(fileExtension) {
console.log("It's an image");
} else if (fileExtension === "js") {
console.log("It's a javascript file");
}
return res.send();
});
But i would recommend to just separate the routes per resource type, for example:
app.get("/img/:fileName", (req, res) => {
console.log(`Getting image ${req.params.fileName}`);
return res.send();
});
app.get("/js/:fileName", (req, res) => {
console.log(`Getting JS file ${req.params.fileName}`);
return res.send();
});
Once the server received the request, you can check for the extension of the url and later process it. [need more information to know exactly what you need]

Multer not populating request body

My web app is making a post request in the form of a multipart form with 2 text fields and one file.
I am able to access the file data perfectly fine via req.file, however the request body is always undefined.
I found some posts suggesting to re-arrange the fields so that the file is the last piece of data in the form... this did not solve the issue either!
Making the post request from front-end
uploadData(fileToUpload, xx, yy) {
const URL = 'http://localhost:5000/api/files/';
this.setState({ uploadingFile: true });
let formData = new FormData();
formData.append('testx', xx);
formData.append('testy', yy);
formData.append('file', fileToUpload);
fetch(URL, {
method: 'POST',
body: formData,
})
Back End handling of request
const multer = require('multer');
const upload = multer({
dest: 'labels/',
fileFilter: function (req, file, cb) {
if (file.mimetype !== 'application/pdf') {
return cb(null, false, new Error('Incorrect file type'));
}
cb(null, true);
},
limits: { fileSize: 100000 },
}).single('file');
...
...
...
router.post('/', checkRequestType, upload, (req, res) => {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
console.log('We got a multer error boys');
console.log(err);
return res.send('Error with multer');
} else if (err) {
console.log('Error - not caused by multer... but during upload');
return res.send('Unknown error during upload');
}
//Always null here?!?!
console.log(req.body);
});
});
There are a couple of issues here. The main one is that you are calling upload twice. The first as a middleware and then you are calling it a second time manually (so that you can handle errors).
You need to change
router.post('/', checkRequestType, upload, (req, res) => {
to this
router.post('/', checkRequestType, (req, res) => {
That should fix the null body issue.
A second issue is that you are passing too many parameters to the cb in this line return cb(null, false, new Error('Incorrect file type')). The first parameter should be the error: return cb(new Error('Incorrect file type'))

Cannot set headers after they are sent to the client when use res.json

I'm setting upload image with multer, multer-s3 but I want to response location file with res.json, an error occurs Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const upload = multer({ storage:
multerS3({
s3,
bucket: process.env.S3_BUCKET_NAME,
key: function(req, file, cb) {
return cb(null, `${Date.now().toString()}-${file.originalname}`)
}
})
})
const singleUpload = upload.single('image', 1)
Step 1:
router.post('/upload', handlers.upload)
upload: (req, res) => {
singleUpload(req, res, function(error) {
// console.log('----------------', req);
if(error) {
return 'Upload image false!!'
}
return res.json({'imageUrl': req.file.location})
})
}
=> Throw error.
Step 2:
router.post('/upload', (req, res) => {
singleUpload(req, res, function(error) {
if(error) {
return 'Upload image false!!'
}
return res.json({'imageUrl': req.file.location})
})
})
=> good run
Someone can help me explain and clear this issue, thanks.

How to upload a file to the server (Node.js)

Don't upload photos to the server, how to solve this problem?
on the page index.ejs a photo gallery should be generated from the added entries. The entry contains a photo. The entry is added, but the photo doesn't load.
project (GitHub)
app/routes.js:
var upload = multer({
storage: storage,
limits: {fileSize: 7},
fileFilter: function (req, file, cd) {
checkFileType(file, cd);
}
}).single('filePhoto');
function checkFiletType(file, cd) {
const fileTypes = /jpeg|jpg/;
const extname = fileTypes.test(path.extname(file.originalname).toLowerCase());
const mimetype = fileTypes.test(file.mimetype);
if (extname && mimetype) {
return cd(null, true);
} else {
cd('Error: only JPEG or JPG!')
}
var Photo = require('../app/models/photo');
module.exports = function (app, passport) {
app.get('/', function (req, res,next) {
Photo.find({}, function (error, photos) {
var photoList = '';
res.render('index.ejs', {photoList: photos});
});
});
}
app.post('/addPhoto', function (req, res, next) {
next();
}, function (req, res) {
var newPhoto = new Photo(req.body);
newPhoto.save().then(function (response) {
console.log('here', response);
res.status(200).json({code: 200, message: 'OK'});
}).catch(function (error) {
console.error('new photo error', error);
});
},function (req, res) {
Photo.find({}, function (error, photos) {
res.send('index.ejs', {
photoList: photos
});
});
});
};
You need to pass your upload var as middleware to your upload route.
Here is a snippet from how I have done it previously:
// Route:
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
router.post('/upload', upload.single('photo'), ImageController.upload);
// Image Controller:
upload(req, res){
console.log("file", req.file)
}
When I post my image, I make sure I call it photo to match the key word I used in my multer middleware:
So I create my form data like so:
const formData = new FormData()
formData.append('photo', {
uri: data.uri,
type: 'image/jpeg',
});
axios.post(`${SERVER}/images/upload`,
formData: formData,
{ headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => console.log("response", response))
.catch(err => console.log('err', err))

Resources