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 -->
Related
I created a Glitch project and I want to upload files to it via user input. I am using express-fileupload and I followed the sample code from their docs to upload a file, but I keep getting an error. I think it might have to do with the directory I am using to move the file to. I have tried using '/app/views/uploads' and 'uploads/' as well as '/assets' (I used assets.js to do so) and I haven't been able to store the file. Here's my code:
var express = require('express');
var fileUpload= require('express-fileupload');
var app = express();
var assets = require("./assets");
app.use("/assets", assets);
app.use(express.static('views'));
app.use(fileUpload());
app.set('view engine', 'ejs');
app.set('views', 'views');
app.get("/", function (request, response) {
response.render('index');
});
app.get('/fileupload', function(req, res) {
res.render('upload');
});
app.post('/upload', function(req, res) {
var sample= req.files.sample;
sample.mv('/assets', function(err) {
if (err)
return res.status(500).send(err);
res.send('File uploaded!');
});
});
var listener = app.listen(process.env.PORT, function () {
console.log('SERVER STARTED ON PORT ' + listener.address().port);
});
The file is received succesfully, so the file not being there is not why I get errors.
I normally get this as the error:
{"errno":-13,"code":"EACCES","syscall":"open","path":"/assets"}
If you know where to upload the files to, please let me know. Any help would be very appreciated!
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.
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);
});
I tried to build a simple node application with routes, but it gives a 404 network error as it's unable to post. Can someone please point out my mistake and correct it?
First I created a directory sampProj, then in it, I've a file - appl.js and a directory routes. Inside routes directory, I've a directory routes and a file main.js. Again inside mainCode directory, I've 3 files - main.js, server.js and index.html.
Sorry for the complicated directions, I wanted to test out small and then start building on it. I want to mention that this code with just server.js and index.html worked without the routes, i.e server.js uses app.post and app.get etc. instead of the corresponding router methods which I've shown below.
So here's the code for the application:
appl.js:
var express = require('express');
var bodyParser = require('body-parser');
var app = module.exports.app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false}));
// parse application/json
app.use(bodyParser.json());
// Adding routes
var server = require(__dirname + '/routes/main');
var mainCode = require(__dirname + '/routes/mainCode/main.js');
app.use('/Service', server);
app.use('/Service/mainCode', mainCode);
// Catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/* Error Handlers */
// It will print the Stacktrace of error
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.send({
message: err.message,
error: err
});
});
}
app.listen(3000,function(){
console.log("Working on port 3000");
});
routes/main.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('<code>Welcome to Service</code>');
});
module.exports = router;
mainCode/main.js:
var express = require('express');
var router = express.Router();
var server = require(__dirname + '/server');
router.use('/server', server);
module.exports = router;
mainCode/index.html
<html>
<head>
<title>Form Data</title>
</head>
<body>
<form id="uploadForm" enctype="multipart/form-data" action="/" method="post">
<input id = "userPhotos" type="file" name="userPhotos" multiple />
<input type='text' id='random' name='random'><br>
<input type="submit" value="Upload" name="submit">
</form>
</body>
</html>
mainCode/server.js:
var express = require("express");
var router = express.Router();
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads/');
},
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + file.originalname);
}
});
var upload = multer({ storage : storage }).any();
router.get('/',function(req,res){
res.sendFile(__dirname + "/index.html");
});
router.post('/',function(req,res){
console.log("posted");
console.log("posted");
console.log(req.body);
upload(req,res,function(err) {
if(err) {
console.error(err);
return res.end("Error uploading file.");
}
console.log(req.body);
console.log(req.files);
res.end("File is uploaded");
});
});
module.exports = router;
Once I open localhost:3000/Service/mainCode/server in a browser, a form is displayed with one text input, but if I submit data, it's redirecting to localhost:3000 with error 404 displayed on the screen.
If you downvote this, please tell me why you're doing so, and in what way I can improve the question.
You access the form via the URL:
http://localhost:3000/Service/mainCode/server
right?
In your mainCode/server.js you set the get as well as the post handling for the same URL.
So why do you call the root directory in mainCode/index.html on form submit:
<form id="uploadForm" enctype="multipart/form-data" action="/" method="post">
it should be:
<form id="uploadForm" enctype="multipart/form-data" action="/Service/mainCode/server" method="post">
as far as I understand.
Usually if you want to send a formular to the same URL you would just leave the action attribute out like:
<form id="uploadForm" enctype="multipart/form-data" method="post">
EDIT: Turned out that it solved the problem for the OP combined with the removing of the attribute enctype, which leads to the default application/x-www-form-urlencoded method.
But as the OP wanted to submit a file in the first place, he had to exchange the body-parser module with multer and set the enctype to multipart/form-data again.
Documentation of multer:
https://github.com/expressjs/multer
I am trying a simple node.js file upload code for test purpose by using express and multer modules.My code look for html like :-
<html>
<head>
<title>File Uploading Form</title>
</head>
<body>
<h3>File Upload:</h3>
Select a file to upload: <br />
<form action="http://127.0.0.1:8081/file_upload" method="POST"
enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="Upload File" />
</form>
</body>
and my server.js code look like :-
var express = require('express');
var app = express();
var fs = require("fs");
var bodyParser = require('body-parser');
var multer = require('multer');
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(multer({ dest: '/tmp/'}));
app.get('/index.html', function (req, res) {
res.sendFile( __dirname + "/" + "index.html" );
});
app.post('/file_upload', function (req, res) {
console.log(req.files.file.name);
console.log(req.files.file.path);
console.log(req.files.file.type);
var file = __dirname + "/" + req.files.file.name;
fs.readFile( req.files.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if( err ){
console.log( err );
}else{
response = {
message:'File uploaded successfully',
filename:req.files.file.name
};
}
console.log( response );
res.end( JSON.stringify( response ) );
});
});
});
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
Now while I run the server.js from command prompt like :- node server.js My server doesn't get started and it throws some error like image :-
SOuřaan Gřg,
Your line, var multer = require('multer'); is returning and object, not the middleware function. There are three middleware functions you can use.
Check out the docs.
In case you need to handle a text-only multipart form, you can use any of the multer methods (.single(), .array(), fields()).
.single(fieldname) Accept a single file with the name fieldname. The single file will be stored in req.file.
.array(fieldname[, maxCount]) Accept an array of files, all with the
name fieldname. Optionally error out if more than maxCount files are
uploaded. The array of files will be stored in req.files.
.fields(fields) Accept a mix of files, specified by fields. An object
with arrays of files will be stored in req.files.
You must change app.use(multer({ dest: '/tmp/'}));. You are passing an object.
Also according to the docs:
WARNING: Make sure that you always handle the files that a user uploads. Never add multer as a global middleware since a malicious user could upload files to a route that you didn't anticipate. Only use this function on routes where you are handling the uploaded files.
You should be assigning the middleware to route in where you are handling the upload. For your case you could do the following:
var upload = multer({ dest: '/tmp/' });
app.post('/file_upload', upload.single('file'), function (req, res, next) {
// req.file is the `file` file
// req.body will hold the text fields, if there were any
})