I have an app to deduce the size of a file uploaded by the user. I have the code as follows
The server.js code is as follows
var express = require('express');
var formidable = require('express-formidable');
var fs = require('fs');
var app = express();
var PORT = 8080;
app.use(express.static(__dirname+'/views'));
app.use(formidable.parse());
app.set('views', './views');
app.set('view engine', 'jade');
app.get('/', function(req, res){
res.render('index.jade');
});
When I try to log the variable stats below, I get an error saying
TypeError: path must be a string
app.post('/upload', function(req, res){
var stats = fs.statSync(req.body);
console.log(stats);
});
app.listen(PORT, function(){
console.log('Express listening on port: '+PORT);
});
The index.jade file is rendered below
html
head
link(rel='stylesheet', href='style.css', type='text/css')
title Upload file for shortening
body
h1 Welcome to file metadata service
div(id='upload-button')
form(action='/upload', enctype='multipart/form-data')
input(name='Upload', type='file', id='upload-butt')
div(id="submit-button")
form(action = '/submit')
button(type="submit", value='Submit', id='submit-butt') Submit
script(src="https://code.jquery.com/jquery-2.2.0.min.js")
script(src="upload.js")
The css styling is below
#submit-butt{
width:100px;
height:auto;
background-color:red;
cursor:pointer;
margin-left:150px;
}
#upload-butt{
width:200px;
height:auto;
cursor:pointer;
float:left;
}
h1{
font-family:Impact;
}
The jQuery code is given below
$('#upload-butt').on('click', function(){
$('#upload-butt').on('change', function(){
var file = $(this).get(0).files;
if(file.length > 0){
var formData = new FormData();
formData.append('Upload', file, file.name);
$.ajax({
url: '/upload',
type: 'POST',
data:formData,
processData:false,
contentType:false,
success: function(data){
console.log('upload successful: '+data);
}
})
}
});
});
How do I deal with the TypeError? How do I convert the path to a string? What I have is the parsed data obtained after running through formidable middleware.
Change the '/upload' in backend to this code. Don't use req parameters in that. No need of that.
app.post('/upload', function(req, res){
// create an incoming form object
var form = new formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/uploads');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name));
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function() {
res.end('success');
});
// parse the incoming request containing the form data
form.parse(req);
});
Related
I am new to node and trying to find a way to load some pdf files in an object from a directory. with an input and then rename the files based on the user input entered. I have 2 problems.
1 problem is the fs.readdirSync(directory); call is running on program start up. I need that call to be made when the page loads.
second problem is I am not finding how to take the value of the input and use the fs.rename to rename the files. Or create new files if necessary.
(this is going to be an internal app used locally only in a small office to rename pdf files for a specific purpose. Not a web app. Just wanted a simple UI for the staff.)
index.js
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var ejs = require('ejs');
var fs = require('fs');
// set the view engine to ejs
app.set('view engine', 'ejs');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/img', express.static(__dirname + '/img'));
//fs
let directory = "img";
let dirBuf = Buffer.from(directory);
// Buffer mydata
function bufferFile(relPath) {
return fs.readdirSync(path.join(__dirname, relPath));
console.log("hello from bufferFile"); // zzzz....
}
// let files = fs.readdirSync(directory);
// console.log(files, "This is the fs.readdirSync");
let files = fs.readdirSync(directory);
console.log(files, "This is the fs.readdirSync");
//routes
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'views/index.html'));
});
//routes
app.get('/new', function(req, res){
// fs.readdir(specs, (err, files) => {
// files.forEach(file => {
// });
// })
res.render('rename',{
files: files,
});
});
app.get('/rename', function(req,res){
res.render('rename',{
files: files,
dirBuf: dirBuf
});
});
app.post('/upload', function(req, res){
// create an incoming form object
var form = new formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/img');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name));
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function() {
res.end('success');
});
// parse the incoming request containing the form data
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
rename.ejs
<!-- views/partials/head.ejs -->
<% include ./partials/head %>
<ul>
<% files.forEach(function(files) { %>
<div class="col-lg-6">
<div class="form-group">
<h3><%= files %></h3>
<object data='img/<%= files %>' type='application/pdf' width='100%' height='250px'></object>
<input class="form-control" id="<%=files.name%>" value="<%=files.name%>">
</div>
</div>
<% }); %>
</ul>
<button type="submit" class="btn btn-primary">Submit</button>
<% include ./partials/footer%>
<!-- views/partials/footer.ejs -->
I am new to Node JS, so things are not coming easy to me. The scenario is I have input field which will accept multiple files.
<input id="upload-input" type="file" name="uploads[]" multiple="multiple">
in my JS script I grab the the change event of this field, and create a post request to my uploader app which is running in different port using formData and ajax post method
$('#upload-input').on('change', function() {
var files = $(this).get(0).files;
if (files.length > 0) {
var formData = new FormData();
formData.append('directory', "path/to/directory");
for (var i = 0; i < files.length; i++) {
var file = files[i];
formData.append('uploads[]', file, file.name);
}
$.ajax({
url: 'https://myurl.com:3000/upload',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data) {
console.log(data);
},
});
}
});
Now the file is sending and in my backend I can upload that using formidable, but the problem is I cannot get the directory value, Here is my code
require('dotenv').load();
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var session = require('express-session');
app.set('views', __dirname + '/public');
app.use('/uploads', express.static(process.env.USER_UPLOADS))
var cors=require('cors');
app.use(cors({origin:true,credentials: true}));
app.post('/upload', function(req, res) {
var user_folder = "path/to/directory/";
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, process.env.USER_UPLOADS + user_folder);
form.on('file', function(field, file) { fs.rename(file.path, path.join(form.uploadDir, file.name)); });
form.on('error', function(err) { console.log('An error has occured: \n' + err); });
form.on('end', function() { res.end('success'); });
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
I tried
console.log(req.body)
but it returns undefined, So how can I get the directory value from my backend?
Thanks in advance.
To fix your issue, I made some changes to your main app's server file
i.e. server.js/app.js/index.js anyone that applies to you. See changes below:
require('dotenv').load();
var express = require('express');
var app = express();
var path = require('path');
var bodyParser = require('body-parser');
var formidable = require('formidable');
var fs = require('fs');
var session = require('express-session');
var cors=require('cors');
app.set('views', __dirname + '/public');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors({ origin:true, credentials: true }));
app.use('/uploads', express.static(process.env.USER_UPLOADS));
app.post('/upload', function(req, res) {
var user_folder = "path/to/directory/";
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, process.env.USER_UPLOADS + user_folder);
form.on('file', function(field, file) { fs.rename(file.path, path.join(form.uploadDir, file.name)); });
form.on('error', function(err) { console.log('An error has occured: \n' + err); });
form.on('end', function() { res.end('success'); });
// Note the changes here
form.parse(req, (error, fields, files) => {
console.log(JSON.stringify({
fields, // { directory: "path/to/directory" }
files // contains the uploaded files
}), null, 2);
});
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
According to the docs at here, form.parse can take an optional callback function.
Parses an incoming node.js request containing form data. If cb is provided, all fields and files are collected and passed to the callback:
form.parse(req, function(err, fields, files) {
// ...
});
I have uploaded the image in to a local directory using Busboy and passed
the path of the image to the MongoDB using Mongoose but now I unable to
retrieve the path
to display the image in my ejs view. I'm new to this nodejs. Please help me
to display the image.
Thank you Very much in Advance :)
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
var nameSchema = mongoose.Schema({
newfile: Object,
path: String
});
var compileSchema = mongoose.model('foods', nameSchema);
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
app.route('/')
.post(function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
//Path where image will be uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
var dirname = path.join(__dirname + '/public/uploads/' + filename);
file.pipe(fstream);
//mongo save
var paths = new compileSchema({newfile : dirname, passReqToCallback: true});
paths.save(function(err){
if(err) throw err;
compileSchema.find({newfile: dirname}, (err, result) =>{
console.log();
return result;
});
});
fstream.on('close', function () {
console.log("Upload Finished of " + filename);
//where to go next
res.redirect('/profile');
});
});
});
app.get('/profile', (req, res)=>{
res.render('profile',{photo: req.result});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
My Ejs file is :
<img src='<%= photo.newfile %>' >
This is the typical process of writing and reading from Mongodb using Mongoose. I have not checked whether your streaming and other things work fine but the db workflow would be better this way.
var express = require('express'); //Express Web Server
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path'); //used for file path
var fs = require('fs-extra'); //File System - for file manipulation
var mongoose = require('mongoose');
var mongoClient = require('mongodb').mongoClient;
var objectId = require('mongodb').ObjectId;
var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/postname');
/* ==========================================================
Create a Route (/upload) to handle the Form submission
(handle POST requests to /upload)
Express v4 Route definition
============================================================ */
app.set('view engine','ejs');
app.use(express.static(__dirname + '/public'));
//You can import your schema like this
const Name = require('./name');
var compileSchema = mongoose.model('foods', nameSchema);
app.get('/', function(req, res, next) {
res.render('index',{'title': 'New post app'});
});
//I have changed your route since it seems to be clashing with the above
app.post('/save' ,function (req, res, next) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
//Path where image will be uploaded
fstream = fs.createWriteStream(__dirname + '/public/uploads/' + filename);
file.pipe(fstream);
var dirname = path.join(__dirname + '/public/uploads/' + filename);
//mongo save
fstream.on('close', function () {
//You can either save to mongodb after streaming closes or while it is streaming but in this case I will do it after.
console.log("Upload Finished of " + filename);
//where to go next
//Declare your schema object here
let name = new Name({
newfile:'Whatever you want to store here',
path: path
});
//Save your declared schema like this
name.save((err) => {
if(err) throw err;
console.log(`saved : ${name}`);
//When you redirect here, it will go to /profile route
res.redirect('/profile');
});
});
});
});
app.get('/profile', (req, res)=>{
//You must retrieve from mongodb your object here if this is where you want the object to be
//{} empty query will find all objects in the table
Name.find({}, (err, result) => {
if(err) throw err;
//after everything was found, send it to front end
res.render('profile',{
photo: req.result,
//Now your 'compileSchema' object is available at front end as 'result' object
result:result
});
});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
name.js (create one schema js file for each table you will be working with)
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let compileSchema = new Schema({
newfile: Object,
path: String
});
let Compile = mongoose.model('Compiles', compileSchema);
module.exports = Compile;
Check first that you are receiving and streaming file correctly. If you are, it must work fine. Also, I don't know why you want to save a newfile:object field but all you really need to do is save the path to the image file then retrieve it where you need to use the image and use the path as the <img src='path'> Refer to the comments.
Trying to send a blob object to my node server. On the client side I'm recording some audio using MediaRecorder and then I want to send the file to my server for processing.
saveButton.onclick = function(e, audio) {
var blobData = localStorage.getItem('recording');
console.log(blobData);
var fd = new FormData();
fd.append('upl', blobData, 'blobby.raw');
fetch('/api/test',
{
method: 'post',
body: fd
})
.then(function(response) {
console.log('done');
return response;
})
.catch(function(err){
console.log(err);
});
}
This is my express route, which uses multer:
var upload = multer({ dest: __dirname + '/../public/uploads/' });
var type = upload.single('upl');
app.post('/api/test', type, function (req, res) {
console.log(req.body);
console.log(req.file);
// do stuff with file
});
But my logs return nothing:
{ upl: '' }
undefined
Been spending a long time on this so any help appreciated!
I was just able to run a minimum configuration of your above example and it worked fine for me.
Server:
var express = require('express');
var multer = require('multer');
var app = express();
app.use(express.static('public')); // for serving the HTML file
var upload = multer({ dest: __dirname + '/public/uploads/' });
var type = upload.single('upl');
app.post('/api/test', type, function (req, res) {
console.log(req.body);
console.log(req.file);
// do stuff with file
});
app.listen(3000);
HTML file in public:
<script>
var myBlob = new Blob(["This is my blob content"], {type : "text/plain"});
console.log(myBlob);
// here unnecessary - just for testing if it can be read from local storage
localStorage.myfile = myBlob;
var fd = new FormData();
fd.append('upl', localStorage.myfile, 'blobby.txt');
fetch('/api/test',
{
method: 'post',
body: fd
});
</script>
The console.log(myBlob); on the frontend is printing Blob {size: 23, type: "text/plain"}. The backend is printing:
{}
{ fieldname: 'upl',
originalname: 'blobby.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: '/var/www/test/public/uploads/',
filename: 'dc56f94d7ae90853021ab7d2931ad636',
path: '/var/www/test/public/uploads/dc56f94d7ae90853021ab7d2931ad636',
size: 23 }
Maybe also try it with a hard-coded Blob like in this example for debugging purposes.
You don't need to use multer. Just use express.raw() inside app.post()
var express = require('express');
var app = express();
app.use(express.static('public')); // for serving the HTML file
app.post('/api/test', express.raw({type: "*/*"}), function (req, res) {
console.log(req.body);
// do stuff with file
});
app.listen(3000);
I know this question has been asked plenty of times before, and I've tried implementing those solutions, but they don't really work for me.
I have been tearing my hair out trying to figure out how to upload a file and read the file size through Node. I initially tried using the formidable npm, which seems to no longer be maintained as I can't find documentation on it. I had no way of dealing with the errors so I tried using multer. However, I repeatedly get an undefined log when I try to log req.file.
I have the server.js code below
var express = require('express');
var formidable = require('formidable');
var multer = require('multer');
var path = require('path');
var upload = multer({dest: './uploads'});
var fs = require('fs');
var app = express();
var PORT = 8080;
app.use(express.static(__dirname+'/views'));
app.set('views', './views');
app.set('view engine', 'jade');
app.get('/', function(req, res){
res.render('index.jade');
});
app.post('/upload', upload.single('Upload'),function(req, res){
console.log(req.file);
});
app.listen(PORT, function(){
console.log('Express listening on port: '+PORT);
});
My javascript code with the AJAX call is provided below
$('#upload-butt').on('change', function(){
var file = $(this).get(0).files;
console.log(typeof file);
if(file.length > 0){
var formData = new FormData();
formData.append('Upload', file, file.name);
$.ajax({
url: '/upload',
type: 'POST',
data:formData,
processData:false,
contentType:false,
error: function(jXhr, status){
console.log('error: '+status);
},
success: function(data){
console.log('upload successful: '+data);
}
})
}
});
My index.jade code is given below
html
head
link(rel='stylesheet', href='style.css', type='text/css')
title Upload file for shortening
body
h1 Welcome to file metadata service
div(id='upload-button')
form(enctype='multipart/form-data', method='post', action='/upload')
input(name='Upload', type='file', id='upload-butt')
div(id="submit-button")
form(action = '/submit')
button(type="submit", value='Submit', id='submit-butt') Submit
script(src="https://code.jquery.com/jquery-2.2.0.min.js")
script(src="upload.js")
I am ready to tear my hair out, so I will be very grateful to anyone who can help me here! Thanks!
You have not applied middle correctly.
You can use something like this:
var express = require('express')
var multer = require('multer')
var app = express()
app.use(multer({ dest: './uploads/'}))
You can access the fields and files in the request object:
console.log(req.body)
console.log(req.files)
So similarly in ur code you have to apply
var express = require('express');
var formidable = require('formidable');
var multer = require('multer');
var path = require('path');
var upload = multer({dest: './uploads'});
var fs = require('fs');
var app = express();
var PORT = 8080;
app.use(upload);
app.use(express.static(__dirname+'/views'));
app.set('views', './views');
app.set('view engine', 'jade');
app.get('/', function(req, res){
res.render('index.jade');
});
app.post('/upload', upload.single('Upload'),function(req, res){
console.log(req.file);
});
app.listen(PORT, function(){
console.log('Express listening on port: '+PORT);
});
You're submitting a different <form> than the one with the image, the correct way is to place all content in a single <form>. This way you're submitting the form which includes the file.
html
head
link(rel='stylesheet', href='style.css', type='text/css')
title Upload file for shortening
body
h1 Welcome to file metadata service
div(id='upload-button')
form(enctype='multipart/form-data', method='post', action='/upload')
input(name='Upload', type='file', id='upload-butt')
button(type="submit", value='Submit', id='submit-butt') Submit
script(src="https://code.jquery.com/jquery-2.2.0.min.js")
script(src="upload.js")
This should work, for the jade part.
(docs about multer)