Kendo UI Angular Upload File to Backend as Node.JS - node.js

I am using Kendo Upload Control to upload files to Node.js backend which used GridFS multer.
Angular
<kendo-upload
[saveField]="file"
[withCredentials]="false"
[saveUrl]="uploadUrl"
(autoUpload)="false"
[multiple]="false"
(select)="selectProfilePic($event)"></kendo-upload>
But the node.js API doesn't pick up the request. I am using [saveField]="file" to pass the uploaded file and the node.js below.
var storage = new GridFsStorage({
//url: mongoose.connection.client.s.url,
//options: options,
db: mongoose.connection,
file: (req, file) => {
return new Promise((resolve, reject) => {
myCrypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: 'uploads'
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
router.post('/upload', upload.single('file'), fileUpload);
module.exports = router;
function fileUpload(req, res) {
console.log("fileUpload")
try {
res.send({ file: req.file })
}
catch(err){
console.log(err);
res.send(err)
}
}
Logs
2019-07-21T19:34:33.679205+00:00 app[web.1]: File Controller
2019-07-21T19:34:33.680436+00:00 app[web.1]: {}
2019-07-21T19:34:33.983631+00:00 app[web.1]: MulterError: Unexpected
field 2019-07-21T19:34:33.983647+00:00 app[web.1]: at
wrappedFileFilter (/app/node_modules/multer/index.js:40:19)
2019-07-21T19:34:33.983649+00:00 app[web.1]: at Busboy.
(/app/node_modules/multer/lib/make-middleware.js:114:7)
2019-07-21T19:34:33.983650+00:00 app[web.1]: at Busboy.emit
(events.js:198:13) 2019-07-21T19:34:33.983670+00:00 app[web.1]: at
Busboy.emit (/app/node_modules/busboy/lib/main.js:38:33)
2019-07-21T19:34:33.983671+00:00 app[web.1]: at PartStream.
(/app/node_modules/busboy/lib/types/multipart.js:213:13)
2019-07-21T19:34:33.983673+00:00 app[web.1]: at PartStream.emit
(events.js:198:13) 2019-07-21T19:34:33.983674+00:00 app[web.1]: at
HeaderParser. (/app/node_modules/dicer/lib/Dicer.js:51:16)
2019-07-21T19:34:33.983675+00:00 app[web.1]: at HeaderParser.emit
(events.js:198:13) 2019-07-21T19:34:33.983677+00:00 app[web.1]: at
HeaderParser._finish
(/app/node_modules/dicer/lib/HeaderParser.js:68:8)
2019-07-21T19:34:33.983678+00:00 app[web.1]: at SBMH.
(/app/node_modules/dicer/lib/HeaderParser.js:40:12)
2019-07-21T19:34:33.983679+00:00 app[web.1]: at SBMH.emit
(events.js:198:13) 2019-07-21T19:34:33.983680+00:00 app[web.1]: at
SBMH._sbmh_feed (/app/node_modules/streamsearch/lib/sbmh.js:159:14)
2019-07-21T19:34:33.983682+00:00 app[web.1]: at SBMH.push
(/app/node_modules/streamsearch/lib/sbmh.js:56:14)
2019-07-21T19:34:33.983683+00:00 app[web.1]: at HeaderParser.push
(/app/node_modules/dicer/lib/HeaderParser.js:46:19)
2019-07-21T19:34:33.983685+00:00 app[web.1]: at Dicer._oninfo
(/app/node_modules/dicer/lib/Dicer.js:197:25)
2019-07-21T19:34:33.983686+00:00 app[web.1]: at SBMH.
(/app/node_modules/dicer/lib/Dicer.js:127:10)
2019-07-21T19:34:33.989908+00:00 heroku[router]: at=info method=POST
path="/v1/file/upload" host=herokuapp.com
request_id=aa1010df-d244-46bc-9b36-f8e437d5ad2a fwd="80.233.46.84"
dyno=web.1 connect=0ms service=312ms status=500 bytes=286
protocol=https

Is there any chance you had to set the field name to some file variable? So, I believe you expected [saveField]="file" to set field name to 'file' string but instead it searches for some this.filevariable which is undefined so you got field name set to the default 'files' value?

Followed #GProst suggestions and analysed a bit and the below fix worked and I don't know the solution yet.
As per the Kendo UI angular documentation,
Sets the FormData key which contains the files submitted to saveUrl.
The default value is files.
So, I just changed the parameter name from file to files and it worked.
const upload = multer({ storage });
router.post('/upload', upload.single('files'), fileUpload);

Related

trying to upload image to nodejs api but it returns with error

I am trying to upload image to my node.js server and when I upload nothing and just send the request to post without image, it works fine but whenever I try to post the image node.js shows error in console
here is the link to post
"http://localhost:3001/databaseGym/logo"
here is my code to handle post operation to that link
Router.post('/logo', upload.single('file'), (req, res) => {
console.log("working");
//res.json({ file: req.file });
res.send("done");
});
and here is my code for upload in upload.single()
// Create storage engine
const storage = new GridFsStorage({
url: url,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: 'logo'
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
and here is the screenshot of postman app through which I am sending image
and here is the error
MulterError: Unexpected field
at wrappedFileFilter (D:\web dev\gym website\server_gym\node_modules\multer\index.js:40:19)
at Busboy.<anonymous> (D:\web dev\gym website\server_gym\node_modules\multer\lib\make-middleware.js:114:7)
at Busboy.emit (node:events:394:28)
at Busboy.emit (D:\web dev\gym website\server_gym\node_modules\busboy\lib\main.js:38:33)
at PartStream.<anonymous> (D:\web dev\gym website\server_gym\node_modules\busboy\lib\types\multipart.js:213:13)
at PartStream.emit (node:events:394:28)
at HeaderParser.<anonymous> (D:\web dev\gym website\server_gym\node_modules\dicer\lib\Dicer.js:51:16)
at HeaderParser.emit (node:events:394:28)
at HeaderParser._finish (D:\web dev\gym website\server_gym\node_modules\dicer\lib\HeaderParser.js:68:8)
at SBMH.<anonymous> (D:\web dev\gym website\server_gym\node_modules\dicer\lib\HeaderParser.js:40:12)
You should change the parameter in Postman from image to file as you specify the property name in the POST endpoint:
// you specify the `file` as the fieldname
Router.post('/logo', upload.single('file'), (req, res) => {
console.log("working");
//res.json({ file: req.file });
res.send("done");
});
From the docs:
.single(fieldname):
Accept a single file with the name fieldname. The single file will be stored in req.file.

Getting MulterError: Unexpected field when adding mutiple file in put request

I am working on uploading multiple files for my product. But when i am trying to make a put request with those files, i got an error from multer on runtime
MulterError: Unexpected field
at wrappedFileFilter (G:\GIT\Mern_Eshop\back-end\node_modules\multer\index.js:40:19)
at Busboy.<anonymous> (G:\GIT\Mern_Eshop\back-end\node_modules\multer\lib\make-middleware.js:114:7)
at Busboy.emit (events.js:315:20)
at Busboy.emit (G:\GIT\Mern_Eshop\back-end\node_modules\busboy\lib\main.js:38:33)
at PartStream.<anonymous> (G:\GIT\Mern_Eshop\back-end\node_modules\busboy\lib\types\multipart.js:213:13)
at PartStream.emit (events.js:315:20)
at HeaderParser.<anonymous> (G:\GIT\Mern_Eshop\back-end\node_modules\dicer\lib\Dicer.js:51:16)
at HeaderParser.emit (events.js:315:20)
at HeaderParser._finish (G:\GIT\Mern_Eshop\back-end\node_modules\dicer\lib\HeaderParser.js:68:8)
at SBMH.<anonymous> (G:\GIT\Mern_Eshop\back-end\node_modules\dicer\lib\HeaderParser.js:40:12)
at SBMH.emit (events.js:315:20)
at SBMH._sbmh_feed (G:\GIT\Mern_Eshop\back-end\node_modules\streamsearch\lib\sbmh.js:159:14)
at SBMH.push (G:\GIT\Mern_Eshop\back-end\node_modules\streamsearch\lib\sbmh.js:56:14)
at HeaderParser.push (G:\GIT\Mern_Eshop\back-end\node_modules\dicer\lib\HeaderParser.js:46:19)
at Dicer._oninfo (G:\GIT\Mern_Eshop\back-end\node_modules\dicer\lib\Dicer.js:197:25)
at SBMH.<anonymous> (G:\GIT\Mern_Eshop\back-end\node_modules\dicer\lib\Dicer.js:127:10)
My code is here
router.put(
'/gallery-images/:id',
uploadOptions.array('images', 10),
async (req, res)=> {
if(!mongoose.isValidObjectId(req.params.id)) {
return res.status(400).send('Invalid Product Id')
}
const files = req.files;
let imagesPaths = [];
const basePath = `${req.protocol}://${req.get('host')}/public/uploads/`;
if(files) {
files.map(file =>{
imagesPaths.push(`${basePath}${file.filename}`);
})
}
const product = await Product.findByIdAndUpdate(
req.params.id,
{
images: imagesPaths
},
{ new: true}
)
if(!product)
return res.status(500).send('the gallery cannot be updated!')
res.send(product);
}
)
Any advice appreciated on where to look ?
This error generally occur when you are sending the name different on Images and using different multer configuration.
uploadOptions.array('images', 10) // check your are sending files with name 'images'
If the name is different, you should put that name instead.

Node: Cannot set headers after they are sent to the client

I did some research on the following error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I understood the idea and what's causing it but I am not sure how to fix it for my controller code:
exports.isServerOnline = (req, res, next) => {
const sock = new net.Socket();
sock.setTimeout(2500);
sock.on('connect', function () {
sock.destroy();
return res.json({
"server": "online"
});
}).on('error', function (e) {
return res.json({
"server": "offline"
});
}).on('timeout', function (e) {
return res.json({
"server": "offline"
});
}).connect(LS_PORT, LS_HOST);
}
I'm using socket to check if a remote host is up or down. Here is my client code (Vue.js):
created() {
this.getServerStatus();
},
methods: {
getServerStatus() {
axios
.get(`${process.env.VUE_APP_BACKEND_URL}/server/status`)
.then(response => {
if (response.data.server === "online") {
// no interesting code here
} else {
// no interesting code here
}
/* eslint-disable no-console */
})
.catch(error => {
console.log(error);
});
}
}
Complete error stack trace:
2020-07-02T07:40:47.743193+00:00 app[web.1]: _http_outgoing.js:518
2020-07-02T07:40:47.743201+00:00 app[web.1]: throw new ERR_HTTP_HEADERS_SENT('set');
2020-07-02T07:40:47.743202+00:00 app[web.1]: ^
2020-07-02T07:40:47.743202+00:00 app[web.1]:
2020-07-02T07:40:47.743204+00:00 app[web.1]: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
2020-07-02T07:40:47.743205+00:00 app[web.1]: at ServerResponse.setHeader (_http_outgoing.js:518:11)
2020-07-02T07:40:47.743206+00:00 app[web.1]: at ServerResponse.header (/app/node_modules/express/lib/response.js:771:10)
2020-07-02T07:40:47.743206+00:00 app[web.1]: at ServerResponse.json (/app/node_modules/express/lib/response.js:264:10)
2020-07-02T07:40:47.743206+00:00 app[web.1]: at Socket.<anonymous> (/app/src/controllers/status.js:15:20)
2020-07-02T07:40:47.743207+00:00 app[web.1]: at Socket.emit (events.js:315:20)
2020-07-02T07:40:47.743207+00:00 app[web.1]: at emitErrorNT (internal/streams/destroy.js:92:8)
2020-07-02T07:40:47.743208+00:00 app[web.1]: at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
2020-07-02T07:40:47.743208+00:00 app[web.1]: at processTicksAndRejections (internal/process/task_queues.js:84:21) {
2020-07-02T07:40:47.743209+00:00 app[web.1]: code: 'ERR_HTTP_HEADERS_SENT'
2020-07-02T07:40:47.743209+00:00 app[web.1]: }
I would highly appreciate if someone could point me on the right track.
I don't think that approach is correct mate. You are trying to create a socket inside http endpoint, that will not work. Here's gist I found that demonstrates using NodeJS Socket.
https://gist.github.com/tedmiston/5935757
I'll recommend using into something like Socket.io. They have good amount of documentation to get off the ground.

Could not connect with MongoLab database URl using node.js and Heroku

I could not connect to MongoDB which is present in MongoLAB . I have one MEAN app and I have deployed in heroku. When I am trying to connect with database but could not. The logs are given below.
Disconnected from log stream. There may be events happening that you do not see here! Attempting to reconnect...
2017-07-31T11:46:48.243603+00:00 app[web.1]: at module.exports (/app/node_modules/mongodb/lib/url_parser.js:59:13)
2017-07-31T11:46:48.243605+00:00 app[web.1]: at Function.MongoClient.connect (/app/node_modules/mongodb/lib/mongo_client.js:113:3)
2017-07-31T11:46:48.243604+00:00 app[web.1]: at connect (/app/node_modules/mongodb/lib/mongo_client.js:289:16)
2017-07-31T11:46:48.243606+00:00 app[web.1]: at run (/app/node_modules/thunky/index.js:13:3)
2017-07-31T11:46:48.243606+00:00 app[web.1]: at /app/node_modules/mongojs/lib/database.js:29:15
2017-07-31T11:46:48.243607+00:00 app[web.1]: at Collection._getConnection (/app/node_modules/thunky/index.js:27:3)
2017-07-31T11:46:48.243608+00:00 app[web.1]: at Collection._getCollection (/app/node_modules/mongojs/lib/collection.js:17:10)
2017-07-31T11:46:48.243609+00:00 app[web.1]: at getCursor (/app/node_modules/mongojs/lib/collection.js:32:10)
2017-07-31T11:46:48.243610+00:00 app[web.1]: at run (/app/node_modules/thunky/index.js:13:3)
2017-07-31T11:46:48.243609+00:00 app[web.1]: at /app/node_modules/mongojs/lib/cursor.js:12:5
2017-07-31T11:46:48.244240+00:00 app[web.1]: [0mPOST /login [31m500 [0m30.134 ms - 22[0m
Disconnected from log stream. There may be events happening that you do not see here! Attempting to reconnect...
My code is below:
var mongoJs=require('mongojs');
var CryptoJS = require("crypto-js");
var database='FGDP';
var collections=['f_users'];
var MONGOLAB_URI="mongodb://username:password#ds127153.mlab.com:27153/fgdp";
var db=mongoJs(MONGOLAB_URI, collections);
var ses;
exports.userlogin=function(req,res){
var username=req.body.user_name;
var password=req.body.user_pass;
// console.log('pass'+typeof(password));
//var ciphertext = CryptoJS.AES.encrypt(password, 'lexelPass');
//var pass=ciphertext.toString();
db.f_users.findOne({'login_name':username},function(err,docs){
console.log('err',err);
if(!err){
if(docs){
var pass=docs.password;
var bytes = CryptoJS.AES.decrypt(pass.toString(), 'lexelPass');
var plaintext = bytes.toString(CryptoJS.enc.Utf8);
if(plaintext==password){
req.session.email=docs.email;
req.session.name=docs.name;
req.session.login_name=docs.login_name;
req.session.status=docs.status;
req.session.user_type=docs.user_type;
res.send(docs);
}else{
res.send("Login failed");
}
}
}
if(err){
res.send("Login failed");
}
})
}
That database and collection is present in mongoLAB. I need to connect it through mongojs. Actally I have a login App and I could not login.
You should do like
var db = mongoJs(MONGOLAB_URI);
db.on('connect', function () {
console.log('database connected')
});

Node.js and Sendgrid mailer error on res.end

I'm a bit new to node. I'm using express and the sendgrid api to send an email (collected REST-fully). After sendgrid succeeds or fails, I want to respond with a json object. Here's the sample case:
var SendGrid = require('sendgrid-nodejs').SendGrid;
var sendgrid = new SendGrid(user, key);
app.get('/LGP/:email', function (req, res){
sendgrid.send({
to: req.params.email,
from: 'me#example.com',
subject: 'Hello World',
text: 'This email sent through SendGrid'
}, function(success, message) {
if (!success) {
console.log(message);
} else {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ result: 'success' }));
res.end(); //error occurs: "Can't use mutable header APIs after sent."
}
}
);
});
On my local server (using foreman), everything works fine. But when I push it to heroku, it gives me this stack trace:
2013-02-27T22:12:46+00:00 app[web.1]: http.js:543
2013-02-27T22:12:46+00:00 app[web.1]: throw new Error("Can't use mutable header APIs after sent.");
2013-02-27T22:12:46+00:00 app[web.1]: ^
2013-02-27T22:12:46+00:00 app[web.1]: Error: Can't use mutable header APIs after sent.
2013-02-27T22:12:46+00:00 app[web.1]: at ServerResponse.getHeader (http.js:543:11)
2013-02-27T22:12:46+00:00 app[web.1]: at /app/node_modules/express/node_modules/connect/lib/middleware/logger.js:229:26
2013-02-27T22:12:46+00:00 app[web.1]: at ServerResponse.<anonymous> (/app/node_modules/express/node_modules/connect/lib/middleware/logger.js:149:20)
2013-02-27T22:12:46+00:00 app[web.1]: at /app/app.js:60:13
2013-02-27T22:12:46+00:00 app[web.1]: at IncomingMessage.<anonymous> (/app/node_modules/sendgrid/lib/sendgrid.js:74:9)
2013-02-27T22:12:46+00:00 app[web.1]: at IncomingMessage.emit (events.js:81:20)
2013-02-27T22:12:46+00:00 app[web.1]: at HTTPParser.onMessageComplete (http.js:133:23)
2013-02-27T22:12:46+00:00 app[web.1]: at CleartextStream.ondata (http.js:1213:22)
2013-02-27T22:12:46+00:00 app[web.1]: at CleartextStream._push (tls.js:291:27)
2013-02-27T22:12:46+00:00 app[web.1]: at SecurePair._cycle (tls.js:565:20)
2013-02-27T22:12:48+00:00 heroku[web.1]: Process exited with status 1
2013-02-27T22:12:48+00:00 heroku[web.1]: State changed from up to crashed
/app/app.js:60:13 refers to the line with "res.end()". What am I doing wrong?
To maximize your chances of your app behaving the same locally and on heroku, you should make sure you specify specific versions for all modules and avoid using "*" for the main dependencies.
Should also should specify the node version in package.json:
"engines": {
"node": "0.8.20"
}
(use whatever version is appropriate).

Resources