I am developing a very simple JavaScript application with NodeJS. Simply upload files and view their content by paragraphs.
The problem is that every time I upload a file, I get the error "No files were uploaded." which corresponds to the following lines:
app.post('/upload_file', (req, res) => {
if (!req.files || !req.files.filetoupload) {
return res.status(400).send('No files were uploaded.');
}
[...]
}
This is the complete code:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
if (!fs.existsSync('./db')) {
fs.mkdirSync('./db');
}
if (!fs.existsSync('./uploads')) {
fs.mkdirSync('./uploads');
}
let db = new sqlite3.Database('./db/paragraphs.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the paragraphs database.');
});
db.run('CREATE TABLE IF NOT EXISTS paragraphs (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT, tag TEXT)', (err) => {
if (err) {
console.error(err.message);
}
console.log('Created paragraphs table.');
});
app.get('/', (req, res) => {
res.send('<h1>Hello World!</h1>' +
'<meta charset="utf-8">' +
'Upload File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
});
app.get('/file_uploading', (req, res) => {
res.send('<h1>File Uploading</h1>' +
'<meta charset="utf-8">' +
'<form action="/upload_file" method="post" enctype="multipart/form-data">' +
'<input type="file" name="filetoupload"><br>' +
'<input type="submit">' +
'</form>');
});
app.post('/upload_file', (req, res) => {
if (!req.files || !req.files.filetoupload) {
return res.status(400).send('No files were uploaded.');
}
let file = req.files.filetoupload;
let filename = file.name;
fs.writeFile('./uploads/' + filename, data, (err) => {
if (err) {
return console.log(err.message);
}
console.log('The file has been saved!');
});
file.mv('./uploads/' + filename, (err) => {
if (err) {
return res.status(500).send(err);
}
res.send('File uploaded!<br>' +
'Upload Another File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
});
fs.readFile('./uploads/' + filename, {encoding: 'utf-8'}, (err, data) => {
if (err) {
return console.log(err.message);
}
let lines = data.split('\n');
for (let i = 0; i < lines.length; i++) {
db.run('INSERT INTO paragraphs (text) VALUES (?)', [lines[i]], (err) => {
if (err) {
return console.log(err.message);
}
});
}
});
});
app.get('/visualize_paragraphs', (req, res) => {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
res.write('<h1>Visualize Paragraphs</h1>');
res.write(row.text + '<br>');
});
res.end();
});
});
app.get('/tag_paragraphs', (req, res) => {
let paragraph_id = req.query.paragraph_id;
let tag = req.query.tag;
if (paragraph_id && tag) {
db.run('UPDATE paragraphs SET tag = ? WHERE id = ?', [tag, paragraph_id], function (err) {
if (err) {
return console.log(err.message);
}
console.log(`Row(s) updated: ${this.changes}`);
});
res.send('<h1>Tag Paragraphs</h1>' +
'<p>Paragraph ' + paragraph_id + ' has been tagged as ' + tag + '</p>');
} else {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
res.write('<h1>Tag Paragraphs</h1>' +
'<table>');
rows.forEach((row) => {
res.write('<tr><td>' + row.id + '</td><td>' + row.text + '</td></tr>');
});
res.write('</table>' +
'<form action="/tag_paragraphs" method="get">' +
'<label for="paragraph_id">Paragraph ID:</label>' +
'<input type="text" id="paragraph_id" name="paragraph_id"><br>' +
'<label for="tag">Tag:</label>' +
'<input type="text" id="tag" name="tag"><br>' +
'<input type="submit" value="Submit">' +
'</form>');
res.end();
});
}
});
app.listen(3000, () => {
console.log('Example app listening on port 3000!');
});
Can you help me? What am I doing wrong?
Try uploading file using Multer Middle ware it will ease out your life, I am attaching a sample code which I used in one of my Project
const express = require('express');
const fs = require('fs');
const Log = require('../utils/Log');
const User = require('../db/models/user_model');
const BandCode = require('../db/models/band_codes')
const UserRouter = new express.Router();
const Response = require('../const/Response');
const auth = require('../middleware/auth');
const path = require('path');
const multer = require('multer')
const sharp = require('sharp')
const appleReceiptVerify = require('node-apple-receipt-verify');
const validator = require('validator');
const { sendPasswordResetEmail } = require('../emails/account');
const { totp } = require('otplib');
const { isError } = require('util');
const key = process.env.TOTP;
totp.options = { step: 1800 }
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, process.env.PUBLIC)
},
filename: (req, file, cb) => {
cb(null, req.user._id + '' + Date.now() + path.extname(file.originalname))
}
});
const upload = multer({
storage,
limits: {
fileSize: 9000000
},
fileFilter(req, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
return cb(new Error('Please upload an image'))
}
cb(undefined, true)
}
})
UserRouter.post('/users/avatar', auth, upload.single('avatar'), async (req, res) => {
console.log("User Image Update Request")
const filepath = process.env.BASE_PATH +req.file.filename;
console.log(filepath)
req.user.imageUrl = filepath;
req.user.avatar = null
// const file = await sharp(req.file.buffer).resize({ width: 250, height: 250 }).png().toFile();
// req.user.avatar = buffer
await req.user.save()
const user = req.user.toObject();
delete user.avatar
delete user.password
delete user.token
delete user.tokens
delete user.socialId
delete user.totop
delete user.buffer
delete user.__v
const response = new Response("SUCCESS", "Image saved", 200, 0, { user });
res.send(response)
}, (error, req, res, next) => {
console.log(error);
res.status(400).send({ error: error.message })
})
module.exports = UserRouter;
From the documentation:
In Express 4, req.files is no longer available on the req object by default. To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty, or pez.
… and you don't have any such middleware loaded.
Ah, I have had the problem before.
It's probably the form type that's being sent by the client.
I would look into multer!
https://www.npmjs.com/package/multer
I think you'll find your solution with that package
you have to use multer for file upload
router.post('/upload-file', upload.single('image'))
const multer = require('multer');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads');
},
filename: function (req, file, cb) {
cb(null , `${Date.now().toString()}-${file.originalname}`);
}
});
const upload = multer({ storage: storage, limits: { fieldSize: 10 * 1024 * 1024 } });
Answer extracted from question, added in behalf of the asker
This is the solution and the fixed code.
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
const multer = require('multer');
const path = require('path');
// Set up multer
const storage = multer.diskStorage({
destination: './uploads/',
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
},
});
const upload = multer({
storage,
dest: './uploads/',
limits: {
fileSize: 1000000
},
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
}
});
// Check if the file is a txt file
function checkFileType(file, cb) {
const filetypes = /\.(txt)$/;
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
const mimetypes = 'text/plain'
mimetype = mimetypes === file.mimetype;
if (mimetype && extname) {
return cb(null, true);
} else {
cb('Error: Only txt files are allowed!');
}
}
// Set up express
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Create directories if they don't exist
if (!fs.existsSync('./db')) {
fs.mkdirSync('./db');
}
if (!fs.existsSync('./uploads')) {
fs.mkdirSync('./uploads');
}
// Connect to the database
let db = new sqlite3.Database('./db/paragraphs.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the paragraphs database.');
});
// Create the paragraphs table if it doesn't exist
db.run('CREATE TABLE IF NOT EXISTS paragraphs (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT, tag TEXT)', (err) => {
if (err) {
console.error(err.message);
}
console.log('Created paragraphs table.');
});
// Home page
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
/*
res.write('<h1>Welcome to the Paragraphs App</h1>' +
'Upload a File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
res.end();
*/
});
app.get('/file_uploading', (req, res) => {
res.sendFile(__dirname + '/file_uploading.html');
});
app.post('/upload_file', upload.single('filetoupload'), async (req, res) => {
let filename = req.file.filename;
res.send('File uploaded!<br>' +
'Upload Another File<br>' +
'Visualize Paragraphs<br>' +
'Tag Paragraphs');
fs.readFile('./uploads/' + filename, {encoding: 'utf-8'}, (err, data) => {
if (err) {
return console.log(err.message);
}
let lines = data.split('\r\n');
for (let i = 0; i < lines.length; i++) {
db.run('INSERT INTO paragraphs (text) VALUES (?)', [lines[i]], (err) => {
if (err) {
return console.log(err.message);
}
});
}
});
});
app.get('/visualize_paragraphs', (req, res) => {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
res.write('<h1>Visualize Paragraphs</h1>');
res.write(row.text + '<br>');
});
res.end();
});
});
app.get('/tag_paragraphs', (req, res) => {
let paragraph_id = req.query.paragraph_id;
let tag = req.query.tag;
if (paragraph_id && tag) {
db.run('UPDATE paragraphs SET tag = ? WHERE id = ?', [tag, paragraph_id], function (err) {
if (err) {
return console.log(err.message);
}
console.log(`Row(s) updated: ${this.changes}`);
});
res.send('<h1>Tag Paragraphs</h1>' +
'<p>Paragraph ' + paragraph_id + ' has been tagged as ' + tag + '</p>');
} else {
db.all('SELECT * FROM paragraphs', (err, rows) => {
if (err) {
throw err;
}
res.write('<h1>Tag Paragraphs</h1>' +
'<table>');
rows.forEach((row) => {
res.write('<tr><td>' + row.id + '</td><td>' + row.text + '</td></tr>');
});
res.write('</table>' +
'<form action="/tag_paragraphs" method="get">' +
'<label for="paragraph_id">Paragraph ID:</label>' +
'<input type="text" id="paragraph_id" name="paragraph_id"><br>' +
'<label for="tag">Tag:</label>' +
'<input type="text" id="tag" name="tag"><br>' +
'<input type="submit" value="Submit">' +
'</form>');
res.end();
});
}
});
app.listen(3000, () => {
console.log('Example app listening on port 3000!');
});
I have this block of code that is not being called for some reason. I would like to know what req.body.rid in the second line is referring to, and if possible, why this block of code is being overlooked.
app.post('/post', function(req, res) {
var curr_rid = req.body.rid;
json.user_data[0]["final_id"] = curr_rid;
let data_final = JSON.stringify(json, null, 2);
var filepath = "data/user_" + amznWorkId + ".json";
fs.writeFileSync(filepath, data_final, (err) => {
if(err) throw err;
});
console.log(json);
});
I am trying to download more that 100 files at the same time. But when I execute the downloading function my macbook freezes(unable to execute new tasks) in windows also no download(but doesn't freeze) and no download progress in both case(idle network).
Here is my download module:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var youtubedl = require('youtube-dl');
var links = require('../models/Links');
router.get('/', function (req, res, next) {
links.find({dlStatus: false}, function (err, docs) {
if (err) {
console.log(err);
res.end();
} else if (!docs) {
console.log('No incomplete downloads!');
res.end();
} else {
for (var i = 0; i < docs.length; i++) {
//todo scraping
var video = youtubedl(docs[i].url, [], {cwd: __dirname});
// Will be called when the download starts.
video.on('info', function (info) {
console.log('Download started');
console.log(info);
});
video.pipe(fs.createWriteStream('./downloads/' + docs[i].id + '-' + i + '.mp4'));
video.on('complete', function complete(info) {
links.findOneAndUpdate({url: info.webpage_url}, {dlStatus: true}, function (err, doc) {
if (err)console.log(err);
else console.log('Download completed!')
});
});
}
}
});
});
module.exports = router;
Now can anyone please help me here? I am using this module for downloading files.
The solution is using async in this case.
Try it this way....with async.each()
var express = require('express');
var router = express.Router();
var fs = require('fs');
var youtubedl = require('youtube-dl');
var links = require('../models/Links');
var async = require('async')
router.get('/', function (req, res, next) {
links.find({dlStatus: false}, function (err, docs) {
if (err) {
console.log(err);
res.end();
} else if (!docs) {
console.log('No incomplete downloads!');
res.end();
} else {
async.each(docs,function(doc,cb){
var video = youtubedl(doc.url, [], {cwd: __dirname});
// Will be called when the download starts.
video.on('info', function (info) {
console.log('Download started');
console.log(info);
});
video.pipe(fs.createWriteStream('./downloads/' + docs.id + '-' + i + '.mp4'));
video.on('complete', function complete(info) {
links.findOneAndUpdate({url: info.webpage_url}, {dlStatus: true}, function (err, doc) {
if (err){
console.log(err);
cb(err);
}
else {
console.log('Download completed!');
cb()
}
});
});
},function(err){
if(err)
return console.log(err);
console.log("Every thing is done,Here!!");
})
}
});
});
module.exports = router;
And you can process every thing in batch too using async.eachLimits().
I'm very new to node and have run into issues with running some functions sequentially and the use of callbacks. I have tried to use the async module, but, I think I'm missing something because it does my functions out of order.
In the most simplest terms I would like to retrieve some data in the form of url params and then:
1. write them to a file
2. lpr print them
3. delete the file
My current code deletes the file before printing.ie step 3 before step 2.Would anyone offer some advice on how best to perform these in order? Thanks in advance.
router.get('/zplprint/:barcode/:zpl', function(req, res) {
var zpl = req.params.zpl;
var filename = appDir + "/uploads/" + req.params.barcode + ".zpl";
console.log(req.params.zpl);
res.send("received zpl: " + req.params.zpl);
async.series([
function(callback){
fs.writeFile(filename, zpl, function(err) {
if(err) {
callback(err);
return;
}
console.log("The file was saved! to "+filename);
callback();
});
},
function(callback){
CupsPrinterName = nconf.get('Print:PrinterName');
console.log(CupsPrinterName);
var cmd = 'lpr -P ' + CupsPrinterName + ' -o raw ' + filename;
exec(cmd, function(error, stdout, stderr) {
// command output is in stdout'
console.log(cmd);
console.log("file printed");
});
callback();
},
function(callback){
fs.unlink(filename, function (err) {
console.log(' deleting ' + filename);
});
callback();
}
]);
});
You are calling the callback() function at the same level of exec(), exec is asynchronous and will log "file printed" after deleting the file because callback() was called outside of exec() and not when the function ends. Try calling callback after printing:
function(callback){
CupsPrinterName = nconf.get('Print:PrinterName');
console.log(CupsPrinterName);
var cmd = 'lpr -P ' + CupsPrinterName + ' -o raw ' + filename;
exec(cmd, function(error, stdout, stderr) {
// command output is in stdout'
console.log(cmd);
console.log("file printed");
callback();
});
},
var Q = require('q')
router.get('/zplprint/:barcode/:zpl', function(req, res) {
var zpl = req.params.zpl;
var filename = appDir + "/uploads/" + req.params.barcode + ".zpl";
console.log(req.params.zpl);
res.send("received zpl: " + req.params.zpl);
function first(callback){
var d1 = Q.defer();
fs.writeFile(filename, zpl, function(err) {
if(err) {
d1.reject(err);
}
console.log("The file was saved! to "+filename);
d1.resolve("success");
});
return d1.promise
}
function second(callback){
var d2 = Q.defer()
CupsPrinterName = nconf.get('Print:PrinterName');
console.log(CupsPrinterName);
var cmd = 'lpr -P ' + CupsPrinterName + ' -o raw ' + filename;
exec(cmd, function(error, stdout, stderr) {
if(error){
d2.reject()
}
console.log(cmd);
console.log("file printed");
d2.resolve()
});
return d2.promise
}
function third(callback){
var d3 = Q.defer()
fs.unlink(filename, function (err) {
if(err){
d3.reject()
}
console.log(' deleting ' + filename);
d3.resolve()
});
return d3.promise
}
first().then(second).then(third).fail(function(){
console.log("Error !!!!")
})
});
Prerequisites:
npm install q
the best ever promise structure
Is there a way to block the asynchronous callback property of node.js?
Please Advice...
For example,
var express = require('express');
var app = express();
var MongoClient = require('mongodb').MongoClient,
format = require('util').format;
var cors = require('cors');
app.get('/gantt', cors(), function (request, response) {
MongoClient.connect('mongodb://127.0.0.1:27017/test', function (err, db) {
if (err) throw err;
var collection = db.collection('ganttdata');
collection.find({}, {
"_id": 0
}).toArray(function (err, results) {
var jsonString = JSON.stringify(results);
response.setHeader('Content-Type', 'text/plain');
response.send('{\"data\":' + jsonString + '}');
});
});
});
app.listen(3000);
console.log('Listening on port 3000...');
Inspite the Node.js prints the console statement first,i want app.get() to be executed.
My scenario is same as that of the above one.
This is my scenario
var ganttresult = new Array();
app.get('/get', cors(), function (request, response) {
console.log('hello');
connection.query("SELECT distinct id FROM ganttdata", function (err, rows) {
if (err) {
console.log('error in fetching ' + err);
} else {
var all_id = rows;
for (var j = 0; j < all_id.length; j++) {
console.log('hello1');
connection.query("SELECT id,tailName FROM ganttdata where id= '" + all_id[j].id + "'", function (err, rows) {
if (err) {
console.log('error in fetching ' + err);
} else {
var jsonString1 = rows;
var set_id = jsonString1[0].id;
connection.query("SELECT item_id,name,start,end FROM ganttdata where id= '" + set_id + "'", function (err, rows) {
if (err) {
console.log('error in fetching ' + err);
} else {
var jsonString2 = rows;
var gantt1 = new Object();
gantt1.id = jsonString1[0].id;
gantt1.tailName = jsonString1[0].tailName;
var series = new Array();
for (var i = 0; i < jsonString2.length; i++) {
var gantt2 = new Object();
gantt2.item = jsonString2[i];
series.push(gantt2);
gantt1.series = series;
}
//console.log(gantt1);
console.log('hi');
ganttresult.push(gantt1);
console.log(ganttresult);
}
});
}
});
}
var result = JSON.stringify(ganttresult);
console.log(result);
response.send('{\"data\":' + result + '}');
response.end();
}
});
});
When I run this code,
I get an empty resultset and when I re-run I get the result.
I guess it is due to asynchronous callback nature of node js.
Please advice...
Thanks
I have tried async.waterfall method as given below
app.get('/get',cors(), function(request,response) {
async.waterfall([
function(result) {
connection.query("SELECT id FROM Gantt",function(err, rows) {
if (err) {
console.log('error in fetching ' + err);
}
else{
var all_id=rows;
for(var j=0;j<all_id.length;j++){
connection.query("SELECT id,tailName FROM Gantt where id= '"+all_id[j].id+"'",function(err, rows) {
if (err) {
console.log('error in fetching ' + err);
}
else{
var jsonString1=rows;
var set_id=jsonString1[0].id;
connection.query("SELECT item_id,name,start,end FROM GanttFlight where id= '"+set_id+"'",function(err, rows) {
if (err) {
console.log('error in fetching ' + err);
}
else{
var jsonString2=rows;
var gantt1=new Object();
gantt1.id=jsonString1[0].id;
gantt1.name=jsonString1[0].tailName;
var series = new Array();
series=[];
for(var i=0;i<jsonString2.length;i++){
var gantt2=new Object();
gantt2.item=jsonString2[i];
series.push(gantt2);
gantt1.series=series;
}
ganttresult.push(gantt1);
}
});
}
});
}
var result= JSON.stringify(ganttresult);
console.log(ganttresult);
response.send(ganttresult);
ganttresult=[];
//response.send('{\"data\":'+result+'}');
response.end();
}
});
}
], function(err, status) {
console.log(status);
});
});
app.listen(3000);
console.log('Listening on port 3000...');
i am getting empty result first and when refresh the browser,i get the required result
Please Advice