Images not uploading to db in nodejs - javascript

I want to edit the image by using put method but when I give the path it shows 'filename' undefined .Image updating but i when skip to edit image then it shows me filename undefined
app.put('/about_update/:id',upload.single('avatar'),(req,res,next)=>{
console.log(res.file);
aboutus.findById(req.params.id,(err,data2)=>{
if(err){
return res.send(err.message, '404 error from server');
}
data2.personName = req.body.personName;
data2.designation = req.body.designation;
data2.content = req.body.content;
data2.avatar = req.file.filename;
data2.save(function(err){
if(err){
res.send(err.message, 'err from server');
}else{
res.json({message:'updated successfully'});
}
})
})
})
error:
events.js:183
throw er; // Unhandled 'error' event
^
TypeError: Cannot read property 'filename' of undefined
at aboutus.findById (/var/www/html/gis-react-version/api/server.js:147:33)
at /var/www/html/gis-react-version/api/node_modules/mongoose/lib/model.js:4451:16
at process.nextTick (/var/www/html/gis-react-version/api/node_modules/mongoose/lib/query.js:2476:28)

if (req.file) {
data.personName = req.body.personName;
data.designation = req.body.designation;
data.content = req.body.content;
data.avatar = req.file.filename;
}else{
data.personName = req.body.personName;
data.designation = req.body.designation;
data.content = req.body.content;
}
aboutus.findByIdAndUpdate(req.params.id, {
$set: {data}
}).then(() => {
res.json({message:'updated successfully'});
}, (err) => {
res.json({message:'err from server'});
})

body-parser handles JSON and urlencoded form submissions, not multipart (which would be the case if you're uploading images).
Thus it is showing this issue.
In order to use that ,you can simply use multer package.

Related

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client -error

I am trying to redirect the page to another page . the first time when I send a post request it works fine but from second post request it gives me this error .
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
Every second time I send the post request it gives me the error.
This is the code
const find_doctor_and_update =(a , p) => {
console.log(a)
patients.findOneAndUpdate({name : a} , { $push :{ patients : p } } , {new : true})
.then(data => {
return data;
})
.catch(err => {
console.log(err);
}) };
router.post('/upload', authorize, upload.single('avatar'), (req, res) => {
console.log(req.body)
var pname = req.session.userid
patient_detail.image_name = `${unique_id}-${req.file.originalname}`;
patient_detail.pid = req.body.pid;
patient_detail.name = req.body.name;
patient_detail.age = req.body.age;
patient_detail.bg = req.body.bg;
prediction_file.stdin.write(`${unique_id}-${req.file.originalname}\n`);
prediction_file.stdout.on('data', (output) => {
if(output == 0){
patient_detail.class = output;
console.log('the output is here')
find_doctor_and_update(pname, (patient_detail))
.then(data => {
console.log(data);
return res.redirect(`/viewpatient/${patient_detail.pid}`);
})
.catch(err => {
//this is the line where i get the error second time when I do post request
console.log(err);
})
}
console.log(`stdout: ${output}`);
})
})
module.exports = router;
I got the mistake I did . I tried to put the output function "prediction_file.stdout" inside the post method . Due to which it was looping back and even if I tried to do return it did not return.

TypeError: res.status is not a function

I'm making a function that permits me to upload a picture to imgur in my express api (nodejs),
i'm encoutering an error when calling a function returning a promise:
TypeError: res.status is not a function
at uploadpicture.then
This is my code:
Where error is raised:
router.post('/upload', (req, res, next)=> {
var busboy = new Busboy({headers: req.headers});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
if(fieldname == 'image') {
// the buffer
file.fileRead = [];
file.on('data', function(data) {
// add to the buffer as data comes in
this.fileRead.push(data);
});
file.on('end', function() {
// create a new stream with our buffered data
var finalBuffer = Buffer.concat(this.fileRead);
upload = uploadpicture(finalBuffer).then((res)=>{ //success request
console.log(res);
res.status(200).json({success: true, message: "Successfully uploaded !", url: res.data.link});
},(err)=>{ //error
res.status(500).json({success: false, message: "Error happenned while uploading !"});
}).catch((error)=>{
console.log(error);
res.status(500).json({success: false, message: "Error happenned while uploading !"});
});
})
}
});
busboy.on('finish', function() {
//busboy finished
});
req.pipe(busboy);
});
And the function :
function uploadpicture(stream){ //get picture stream
return new Promise((resolve, reject)=>{
var options = {
uri: 'https://api.imgur.com/3/image',
method: 'POST',
headers: {
//'Authorization': 'Client-ID ' + config.client_id_imgur // put client id here
},
formData: {
image: stream,
type: 'file'
},
auth: {
bearer: config.access_token_imgur,
}
};
request(options)
.then((parsedBody)=> {
resolve(parsedBody);
})
.catch((err)=> {
console.log(err);
reject(err.toString())
});
});
}
The code works perfectly, but i don't know why suddendly this error happened,
i tried to :
change arrow functions to function(){}
Add next to the route parameters
Nothing worked, Thanks for your help
The accepted answer directly addresses the OP's problem, but I post another solution since you can also encounter this error in other places.
When you have:
api.use((error: ErrorRequestHandler, request: ExpressRequest, response: ExpressResponse) => {
response.status(500).end() // response.status is not a function
})
Because the error handling route must accept 4 arguments for express to identify it as an error middleware.
api.use((error: ErrorRequestHandler, request: ExpressRequest, response: ExpressResponse, next: NextFunction) => {
response.status(500).end()
})
Just adding the next function (or whatever argument you're missing) will fix it.
https://github.com/visionmedia/supertest/issues/416#issuecomment-514508137
At this point:
upload = uploadpicture(finalBuffer).then((res)=>{ //success request
the resis the result of promise uploadpicture function (that is the parsedBody), not the res from the express route. So indeed, it has no status function. Try change the then callback name like:
upload = uploadpicture(finalBuffer).then((otherName)=>{ //success request
You are getting this error:
TypeError: res.status is not a function
Because the order should be (err, res, req, next) not (req, res, err, next),
example below
const errorHandler = (err, req, res, next) => {
const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
res.status(statusCode)
res.json({
message : err.message,
stack :process.env.NODE_ENV === 'production' ? null : err.stack,
})
}
Order of parameters really matters i had error in below code
const getImagesByBrand = async (res) => {
try {
const images = await Image.find();
res.status(200).json(images);
} catch (error) {
res.status(500).json(error);
}
};
I was not giving req as parameter and that was the reason for error i just add req,res and it worked
If you are using the async/await method:
const notifications = await notifications.aggregate({...})
if(notifications){
return res.status(200).json({ data: notifications })
}else{
return res.status(404).json({ message: 'No notifications found'})
}
Make sure that you are including your return statements. Not including a return statement will cause this. Something else that I was doing is I had JSON instead of json, which will most definitely throw an error.

Why isn't this exported Gridfs function executing correctly?

I am working on a React application with a node and mongo backend. The mongo backend is going to be storing images using Gridfs-stream. I have implemented the saving of images successfully, but now am having trouble pulling specific images from the database.
The function for gfs.files.findOne was working correctly until I moved it to a separate file and added it to the module exports. I can't figure out what could be causing this to fail executing.
Getting image in database.js:
exports.getFile = (filename) => {
console.log('loading file: ' + filename);
gfs.files.findOne({ filename : filename }, (err, file) => {
console.log('finding file');
if (file) {
// checking specifically for image here
if (file.contentType == 'image/png' || file.contentType == 'image/jpeg') {
res.set('Content-Type', file.mimetype);
const readstream = gfs.createReadStream(file.filename);
console.log('returning readstream');
return readstream;
}
else {
console.log('error loading');
const err = { "status": "error", "details": "File is not an image" };
return err;
}
}
else {
console.log('error loading');
const err = { "status": "error", "details": "Failed to find specified file" };
return err;
}
});
console.log('function ending');
}
Calling the function in the api route users.js:
let rs = database.getFile(pic.profilePicture);
if (rs.status && rs.status === "error") {
res.json(rs);
}
else {
// we have a readstream
rs.pipe(res);
}
Console output in terminal:
[0] testing retrieving profile picture
[0] loading file: 7be7c6a99a96023763b753febd85a92e.png
[0] function ending
[0] events.js:173
[0] throw er; // Unhandled 'error' event
[0] ^
[0]
[0] TypeError: Cannot read property 'status' of undefined
[0] at User.getProfilePicture (/Users/zachdobbs/Documents/Projects/Better/routes/api/users.js:44:20)
[0] at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/model.js:4698:16
[0] at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:4099:12
[0] at process.nextTick (/Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:2681:28)
[0] at processTicksAndRejections (internal/process/next_tick.js:74:9)
[0] Emitted 'error' event at:
[0] at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/model.js:4700:13
[0] at /Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:4099:12
[0] at process.nextTick (/Users/zachdobbs/Documents/Projects/Better/node_modules/mongoose/lib/query.js:2681:28)
[0] at processTicksAndRejections (internal/process/next_tick.js:74:9)
[0] [nodemon] app crashed - waiting for file changes before starting...
As far as I can see the gfs.files.findOne function is skipping over the entire block and going straight to the end of the function. The only logs being shown are the loading file: ...png and function ending outputs. These logs are found at the beginning and end of the function, but none of the other logs within the function are being executed. I can not figure out why this may be the case. If anyone could help me solve this it would be greatly appreciated.
Like this:
exports.getFile = (filename) => {
console.log('loading file: ' + filename);
gfs.findOne({ filename : filename }, (err, file) => {
console.log('finding file');
if (file) {
// checking specifically for image here
if (file.contentType == 'image/png' || file.contentType == 'image/jpeg') {
res.set('Content-Type', file.mimetype);
const readstream = gfs.createReadStream(file.filename);
console.log('returning readstream');
return readstream;
}
else {
console.log('error loading');
const error = { status: "error", details: "File is not an image" };
return error;
}
}
else {
console.log('error loading');
const error = { status: "error", details: "Failed to find specified file" + err };
return error;
}
});
console.log('function ending');
}
and then:
let rs = database.getFile(pic.profilePicture);
if (rs.status && rs.status === "error") {
res.json(JSON.stringify(rs));
}
else {
// we have a readstream
rs.pipe(res);
}

Using Multer to handle formdata

I have this code that creates a project and uploads the image to Amazon S3.
I am using Bodyparser middleware to handle the data coming from the client but after some research I found out that it doesn't handle formdata. I need to use multer or some library like that.
Here is my attempt to use multer:
In my routes folder that handles the Post request to the Create function, I added it like this:
import multer from 'multer';
const upload = multer();
routes.post(
'/',
upload.any('projectImage'),
ProjectController.create,
);
Here is the Create function:
export async function create(req, res, next) {
const body = req.body;
S3Upload(req, res, async (s3err, s3res) => {
if (s3err) {
res.send('Error occured uploading image')
} else if (s3res && s3res.Location) {
body.projectImage = s3res.Location
try {
return res
.status(HTTPStatus.CREATED)
.json(await Project.createProject(body, req.user._id));
} catch (err) {
err.status = HTTPStatus.BAD_REQUEST;
return next(err);
}
} else {
res.send('Error creating project.')
}
});
}
Now when I send a post request to the /project routes. I get this error:
(node:77236) UnhandledPromiseRejectionWarning: TypeError: (0 , _s2.default) is not a function
(node:77236) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
PS. The Create function works perfectly without adding the S3Upload. & the S3Upload also works perfectly if I am only sending a file. The only time when it doesnt work is when I send mix data. i.e. a form with some text fields and a file.
I didn't post the S3Upload function but if anyone is curious, let me know I will share the code for it.
UPDATE
export async function S3Upload(req, res, callback) {
const chunks = [];
let fileType;
let fileEncodingType;
const busboy = new Busboy({
headers: req.headers,
});
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
filename.replace(/ /g, "_");
fileType = mimetype;
fileEncodingType = encoding;
file.on('data', data => {
chunks.push(data)
});
file.on('end', () => {
console.log(`File [${filename}] Finished`);
});
});
busboy.on('finish', () => {
const userId = UUID();
const params = {
Bucket: BUCKET_NAME,
Key: userId,
Body: Buffer.concat(chunks),
ACL: ACL,
ContentEncoding: fileEncodingType,
ContentType: fileType
}
S3.upload(params, (err, s3res) => {
if (err) {
callback(err);
} else {
callback(null, s3res);
}
});
});
req.pipe(busboy);
}

Error: parser error, 0 of 4344 bytes parsed (Node.js)

I am trying to use an upload program to upload my files. The code that I use is
app.post('/photos',loadUser, function(req, res) {
var post = new Post();
req.form.complete(function(err, fields, files) {
if(err) {
console.log(err);
next(err);
} else {
ins = fs.createReadStream(files.file.path);
ous = fs.createWriteStream(__dirname + '/public/uploads/photos/' + files.file.filename);
post.filename=files.file.filename;
post.file=files.file.path;
util.pump(ins, ous, function(err) {
if(err) {
next(err);
} else {
post.save(function(err,docs) {
req.flash('info', 'information Saved');
res.redirect('/photos');
});
}
});
}
});
});
When I remove loadUser method everything is working fine, but when I use the loadUser method it is giving me an error. The console information of the error is:
Error: parser error, 0 of 4344 bytes parsed
at IncomingForm.write (/home/darhamid/node_modules/formidable/lib/incoming_form.js:141:17)
at IncomingMessage.<anonymous> (/home/darhamid/node_modules/formidable/lib/incoming_form.js:91:12)
at IncomingMessage.emit (events.js:67:17)
at HTTPParser.onBody (http.js:121:23)
at Socket.ondata (http.js:1349:22)
at TCP.onread (net_uv.js:312:27)
The error is caused only when i use loadUser function, if i remove the loadUser Funciton everything is working fine.
I don't know the reason behind this and am stuck. Can anyone help me please?
See this github issue : https://github.com/felixge/node-formidable/issues/34
Another possible cause for the problem is in this line:
request.setEncoding( "utf8" );
You are trying to perform database operation before everything, which is creating problems for you. Try the following code:
app.post('/potos', function(req, res, next) {
//req.form.pause();
req.form.complete(function(err, fields, files) {
if(err) {
next(err);
} else {
ins = fs.createReadStream(files.file.path);
ous = fs.createWriteStream(__dirname + '/public/uploads/photos/' + files.file.filename);
var post = new Post();
post.filename=files.file.filename;
post.file=files.file.path;
post.created_at = new Date();
post.user_id = req.session.user_id;
function postCreationFailed() {
req.flash('error', 'Unable to Download ');
res.render('photos/new', {
locals: {
post: new Post(),currentUser: req.session.user_id
}
});
}
util.pump(ins, ous, function(err) {
if(err) {
next(err);
} else {
console.log('\nuploaded %s to %s', files.file.filename, files.file.path);
post.save(function(err) {
if (err)
return postCreationFailed();
req.flash('info', 'photos Succesfully Uploaded');
res.redirect('/user/photos/'+post.user_id);
});
}
});
}
});
req.form.on('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write('Uploading: %' + percent + '\r');
});
});
Good luck...

Categories