I am very new to node.js and have been googling for a solution to the problem stated in my question title above.
Basically I am building a simple web api that allows users to upload their files and then query them individually after that. So I am trying to figure out how to display the list of files in the server directory so instead of them remembering the exact file name, they can pick it from the list.
Here's my full html code project/public/index.html (EDIT - after answered by Oorja)
<!DOCTYPE html>
<html>
<head>
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
</head>
<style>
.dropdown-content {
display: none;
position: absolute;
background-color: #f6f6f6;
min-width: 230px;
overflow: auto;
border: 1px solid #ddd;
z-index: 1;
}
.show {display:block;}
</style>
<body>
<h1>api service</h1>
<br>
<div id="upload_form">
<h3>Upload images</h3>
<form action="/api/uploadImages" method="post" enctype="multipart/form-data">
<input type="file" name="image" multiple="multiple"><br><br>
<input type="submit" value="Upload">
</form>
</div>
<div id="query_images">
<h3>Query images</h3>
<form action="/api/queryImages" method="get" enctype="text/plain">
<input type="text" name="image_name"><br><br>
<input type="submit" value="Query">
</form>
</div>
<div class="dropdown">
<button onclick="show_list()" class="dropbtn">Images</button>
<div id="image_list" class="dropdown-content">
<input type="text" placeholder="Search for your images..." id="userInput">
</div>
</div>
<script>
function show_list() {
var image_list = document.getElementById("image_list");
$.getJSON('http://localhost:8080/list-files', function(data) {
data.forEach(function(file) {
$(image_list).append($('' + file + ''));
})
});
}
</script>
</body>
</html>
And below is the javascript full code project/server.js (EDIT - after answered by Oorja)
var express = require('express'),
multer = require('multer'),
bodyParser = require('body-parser'),
path = require('path')
fs = require('fs');
var app = express();
var imageStorage = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, './uploaded_files');
},
filename: function(req, file, callback) {
callback(null, file.fieldname + '_' + Date.now() + '_' + file.originalname);
}
});
var upload = multer({
storage: imageStorage,
fileFilter: function(req, file, callback) {
console.log('Checking file extension...');
var extension = path.extname(file.originalname);
if (extension == '.jpg' || extension == '.png' || extension == '.jpeg') {
console.log('Extension looks good!');
callback(null, true);
} else {
callback('Please upload images only!', false);
}
}
}).array('image');
app.use(bodyParser.json());
app.use('/uploaded_files', express.static('./upload_files'));
// define http methods handlers
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'public', 'index.html'))
});
app.get('/list-files', function(req, res) {
var files = fs.readdirSync('./uploaded_files');
res.json(files);
})
app.get('/api/queryImages', function(req, res) {
var imageName = req.query.image_name
console.log(imageName);
res.sendFile(path.join(__dirname, 'uploaded_files', imageName));
});
app.post('/api/uploadImages', function(req, res) {
upload(req, res, function(err) {
if (err) {
console.log(err);
return res.end('Something went wrong!');
}
console.log('Upload successful!')
res.send('Successfully uploaded images!');
});
});
app.listen(port=8080, function(a) {
console.log('Listening to port ' + port);
});
The javascript works /list-files as I can see the list of files in my console or if I go to /list-files url, however, I cannot figure out how to send the output to front end - I don't know how to connect them - so then when I click on the button under div class="dropdown" they will appear as a list <a> element.
Could someone please point me in the right direction or even better, give me an example?
Thank you in advance!
EDIT
Output of files from the javascript above /list-files is as below
[ '.DS_Store',
'Screen Shot 2018-06-02 at 2.15.10 pm.png',
'aaa.png',
'bbb.png',
'ccc.png',
'ddd.png',
'eee.png' ]
Also, to clarify, I am using Express framework to build this web api.
Once you have the list of files ready, make an API end-point for it. Say, /get-files. Assuming you're using express as a node.js server, you can do this -
const express = require('express');
const fs = require('fs');
const app = express();
// Makes your upload_files directory public. Don't use this in a real app.
// Create a separate route to serve file data. This is just for brevity of code.
app.use('/upload_files', express.static('./upload_files'))
app.get('/get-files', (req, res) => {
// your logic of getting file names
const files = fs.readdirSync('./upload_files');
res.json(files);
});
app.listen(3000); // start a server at localhost:3000
Now, on your frontend, you can open an XHR GET request to fetch the name of files you have on the node.js server like so -
function show_list() {
var image_list= document.getElementById('image_list');
// Assuming you have jQuery as well...
$.getJSON('http://localhost:3000/get-files', function (data) {
data.forEach(file => {
// Do something with the file name
$(image_list).append($('' + file + ''));
})
});
}
You can read more about Express here.
You can also do what Tamas has done with Server-side templating. It will send the data along with the HTML file but I doubt if that is what you asked for.
You should try a template engine like EJS.
Example usage if you use express:
EJS uses the views folder in root for html files default, so create it and put your index.html there.
0. Install EJS: npm install ejs
1. Include EJS in express: app.set('view engine', 'ejs');
2. Add to your route: res.render('index', {files: files});
3. Get it in HTML, modify your index.html (put it where you need):
<% for (var i = 0; i < files.length; i++) { %>
<%= files[i] %>
<% }; %>
Or if you need it as a JS variable use:
<script> var files = <%- JSON.stringify(files) %>; </script>
More information
Related
I'm trying to build very simple web page (one page , spited into 2 parts, each part will have it's own html file):
Welcome.html & Welcome.css:
<html>
<head>
<link rel="stylesheet" type="text/css" href="Welcome.css">
</head>
<body id="bodyTag">
<script type = "text/javascript" src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type = "text/javascript">
$(document).ready(function(){
});
</script>
<div id="top" w3-include-html="/Top.html">
</div>
<div id="bottom">
bottom
</div>
</body>
</html>
#bottom {
height: 50%;
background-color: blue;
}
#top {
height: 50%;
background-color: orange;
}
I want that Welcome.html file will get the top content from external html file
Top.html
<html>
<head>
</head>
<body>
Test -> TOP
</body>
</html>
But is seems that there is no request for Top.html file in the Node.js Log:
var express = require('express');
var app = express();
var fs = require('fs');
var bodyParser = require('body-parser');
app.use(bodyParser.json())
/*
* Home page
*/
app.get('/', function (req, res) {
clearLogScreen();
console.log("[/] Got request for '/'");
res.sendFile( __dirname + '/Welcome.html');
})
app.get('/Welcome.css', function(req, res) {
console.log("[/Welcome] Got request for 'Welcome.css'");
res.sendFile(__dirname + "/" + "Welcome.css");
});
app.get('/Top', function(req, res) {
console.log("[/Top] Got request for 'Welcome.top'");
res.sendFile(__dirname + "/" + "Top.html");
});
/*
* Startup
*/
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
// start
console.log("-----------------------------")
console.log("Dirname: " + __dirname);
console.log("App listening at http://%s:%s", host, port)
})
I guess I'm missing something very easy, but can't find the mistake.
Kindly checkout templatesjs; It will help insert html inside another html.
I'm not sure what "w3-include-html" is, but if it does what it is supposed to do (based on the name), then try changing its value from "/Top.html" to "/Top". Or, alternatively, try changing the url route "/Top" to "/Top.html" in your express app.
One side note: Your included html ("Top.html") should not be a complete html. Try removing html, header and body tags. It should be a fragment.
js application. Need help to resolve this issue.
I have app.js which is node, calls index.html. The index.html intern calls main.js function clicked. It works fine when I have funtion 'clicked()' embeded inside index.html using script tag. But does not work if function clicked is in a seperate js file. I think this is something regarding to node.js but unable to figure out. Please find my code below.
app.js
var http = require('http');
var fs = require('fs');
var express = require('express');
var path = require('path');
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
var request = require('request');
request('http://localhost:8000/test', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
});
var server = http.createServer(function(req,res){
console.log('Request was made:' + req.url);
res.writeHead(200,{'content-Type': 'text/html'});
var myReadStream = fs.createReadStream(__dirname + '/index.html','utf8');
myReadStream.pipe(res);
});
server.listen(3000,'127.0.0.1');
console.log('Listening on port 3000');
index.html
<!DOCTYPE html>
<html>
<head>
<title> Login</title>
<script type="text/javascript" src="main.js"></script>
<center>
<h1> Login </h1>
</center>
</head>
<body>
<center>
<input type="text" id="username" placeholder="UserName"></br>
<input type="password" id="password" placeholder="PassWord"></br>
<input type="button" value="Login" onclick="clicked()">
</center>
</body>
</html>
main.js
function clicked() {
var user = document.getElementById('username');
var pass = document.getElementById('password');
var checkuser = "test";
var checkpass = "123"
if (user.value == checkuser) {
if (pass.value == checkpass) {
window.alert("You are logged in as "+ "'"+user.value+"'");
open("http://www.yahoo.com");
}
else
window.alert("Incorrect username or Password");
}
else
window.alert("Incorrect username or Password");
}
ScreenShot of the Error:
This is because the Node.js server does not serve main.js correctly -- According to the browser's "Resources" panel, main.js is available, but its path is not /main.js.
Low level Node.js server code and Express framework code co-exist, which is not a good idea.
To solve the problem with low level Node.js code:
var server = http.createServer(function(req,res){
console.log('Request was made:' + req.url);
if (req.url === '/main.js') {
res.writeHead(200,{'content-Type': 'application/javascript'});
var jsReadStream = fs.createReadStream(__dirname + '/main.js','utf8');
jsReadStream.pipe(res);
return;
}
res.writeHead(200,{'content-Type': 'text/html'});
var myReadStream = fs.createReadStream(__dirname + '/index.html','utf8');
myReadStream.pipe(res);
});
To solve the problem with Express framework:
var http = require('http');
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/main.js', function(req, res) {
res.sendFile(path.join(__dirname + '/main.js')); // where main.js located.
});
app.set('port', 3000);
var server = http.createServer(app);
server.listen(port);
You are using both http and express, which is probably unnecessary. I would serve static files with app.use(express.static('public')), per the docs. Then you can serve the index with
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/index.html'))
});
And start the server with app.listen(3000);
Unresolved function or method get().
I'm new in js and node and I got stuck with this while trying to make a chat using sockets. Here is the code:
.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
server.listen(8888);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.on('send message', function (data) {
io.sockets.emit('new message', data);
});
});
.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>glupi chat</title>
<style>
#chat{
height: 500px;
}
</style>
</head>
<body>
<div id="chat"></div>
<form id="send-message">
<input size="35" id="message">
<input type="submit">
</form>
<script src='jquery-3.2.1.js'></script>
<script src="/socket.io/socket.io.js"></script>
<script>
$document.ready(function () {
var socket = io.connect();
var $messageForm = $('#send-message');
var $messageBox = $('#message');
var $chat = $('#chat');
$messageForm.submit(function (e) {
e.preventDefault();
socket.emit('send message', $messageBox.val());
$messageBox.val('');
});
socket.on('new message', function (data) {
$chat.append(data + "<br/>");
});
});
</script>
</body>
</html>
I'm using IntelliJ IDEA, I have every module and library that I need installed.
It appears that you have no route for the jQuery file you specify with this:
<script src='jquery-3.2.1.js'></script>
A nodejs express server does not server ANY files by default so unless you have a general purpose route for your static files or a specific file for that jQuery file, your express server will not know how to serve that file when the browser requests it.
You have several possible choices for how to fix that:
Change the jQuery URL in the script tag in your web page to point to one of the public CDNs for jQuery. There are often performance advantages to doing this. For example, you could change to this: <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>.
Use express.static() on your server to configure a directory of static assets that will be automatically served by express when requested by the browser.
Create a specific route for the jQuery file just like you did with your exist app.get('/', ...)that responds to the/` GET request.
I have a script that takes a picture from my webcam.
it's working fine when i runs locally or when i see in a online server.
But when i run the html file from the node.js, it doesnt show the view from my webcam.
how to fix that?
MY SERVER IN NODE:
// app.js
var http = require('http');
var fs = require('fs');
sys = require('util');
var server = http.createServer(function(request, response){
fs.readFile(__dirname + '/index.html', function(err, html){
console.log("oi");
response.writeHeader(200, {'Content-Type': 'text/html'});
response.write(html);
response.end();
});
});
server.listen(3000, function(){
console.log('Executando Servidor HTTP');
});
MY HTML:
<!DOCTYPE html>
<html>
<head>
<title>Javascript Webcam Demo - <MyCodingTricks/></title>
</head>
<body>
<h3>Demonstrates simple 320x240 capture & display</h3>
<div id="my_camera"></div>
<!-- A button for taking snaps -->
<form>
<input type=button class="btn btn-success" value="Take Snapshot" onClick="take_snapshot()">
</form>
<div id="results" class="well">Your captured image will appear here...</div>
<!-- First, include the Webcam.js JavaScript Library -->
<script type="text/javascript" src="2/webcam.min.js"></script>
<!-- Configure a few settings and attach camera -->
<script language="JavaScript">
Webcam.set({
width: 320,
height: 240,
image_format: 'jpeg',
jpeg_quality: 90
});
Webcam.attach( '#my_camera' );
function take_snapshot() {
// take snapshot and get image data
Webcam.snap( function(data_uri) {
// display results in page
document.getElementById('results').innerHTML =
'<h2>Here is your image:</h2>' +
'<img src="'+data_uri+'"/>';
Webcam.upload( data_uri, 'upload.php', function(code, text) {
// Upload complete!
// 'code' will be the HTTP response code from the server, e.g. 200
// 'text' will be the raw response content
});
} );
}
</script>
</body>
</html>
Your program seems to be sending the content of index.html for every request (for html, icons, scripts, etc.). Maybe try using express to serve static files properly:
var express = require('express');
var app = express();
app.use('/', express.static(__dirname));
app.listen(3000, function(){
console.log('Executando Servidor HTTP');
});
It's even easier than the way you want to write it, because to make your script work you would have to manually route the requests based on the request object to properly send scripts and different assets, make sure to handle MIME types, paths like ../.. etc.
Also you may want to move your static files (html, css, js) to a different directory like static and change the app.js like this:
var express = require('express');
var app = express();
app.use('/', express.static(__dirname + '/static'));
app.listen(3000, function(){
console.log('Executando Servidor HTTP');
});
so that no one will be able to get your app.js code by browsing to: http://localhost:3000/app.js
I'm a real noob when it comes to nodejs, jsut started this a couple of days ago. I can't figure out why my js and css files aren't applied. There are no 404 errors so that doesn't seem to be it. I'm trying to read the files using express. I'm getting these console errors in dev tools:
GamblerScript.js:1 Uncaught SyntaxError: Unexpected token <
jquery-2.2.0.min.js:1 Uncaught SyntaxError: Unexpected token <
localhost/:5 Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:8080/css/Stylesheet.css".
(index):9 Uncaught ReferenceError: Run is not defined
Is there any one who can see what i'm doing wrong?
var http = require('http');
var fs = require('fs');
var index = fs.readFileSync('index.html');
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.sendfile('/index.html');
});
app.use(express.static(__dirname + '/public'));
fs.readFile('./index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8080);
});
<html lang="en">
<head>
<title>Dices</title>
<link rel="stylesheet" href="/css/Stylesheet.css">
<script src="/js/GamblerScript.js"></script>
<script src="/js/jquery-2.2.0.min.js"></script>
</head>
<body onload="Run();">
<div id="spinboxcontainer">
<div class="spinbox">
<span class="spinspan">Dices</span>
</div>
<div id="container">
<div id="spinner1" class="spinner">
<div id="D1.1" class="one">1</div>
<div id="D1.2" class="two">2</div>
<div id="D1.3" class="three">3</div>
<div id="D1.4" class="four">4</div>
<div id="D1.5" class="five">5</div>
<div id="D1.6" class="six">6</div>
</div>
</div>
<div id=container2>
<div id="spinner2" class="spinner">
<div id="D2.1" class="one">6</div>
<div id="D2.2" class="two">5</div>
<div id="D2.3" class="three">4</div>
<div id="D2.4" class="four">3</div>
<div id="D2.5" class="five">2</div>
<div id="D2.6" class="six">1</div>
</div>
</div>
</div>
</body>
</html>
function Run(){
alert('Welcome');
var clickNumber = 1;
document.getElementById('spinner1').addEventListener("click", function(){
alert('Your click is number ' + clickNumber + '!');
document.body.className -= ' WhiteBackground';
clickNumber = clickNumber + 1;
});
document.getElementById('spinner2').addEventListener("click", function(){
alert('Your click is number ' + clickNumber + '!');
document.body.className += ' WhiteBackground';
clickNumber = clickNumber + 1;
});
};
You messing up different approaches. If you use express there is no need to http.createServer and manually read your static files with fs.readFile. For simple static server just simplify your main file like this
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080, function() {console.log('server listening on port 8080...')})
The error you've got is because whenever the browser asks server for script files like jquery and GamblerScript your custom http server sends your index.html file back and browser tryes execute it like javascript.
There are a few things you are doing wrong.
In the bottom half of your code, in the callback passed to fs.readFile(), you create a Node server to handle all requests. The emphasized words are key here: you are creating a server using only Node's built-in features, which you shouldn't need to do when using Express; and the server handles all requests, not just those to your index.html file, as I think you intended. So, when the requests for your CSS and JavaScript come in, you are sending index.html as a response. This won't do.
Luckily, the solution is simpler than the original problem. Just do this:
'use strict';
const path = require('path');
const express = require('express');
const app = express();
// This just lets you set an alternate port with an environment variable,
// if you want.
const PORT = process.env.PORT || 8080;
// Set your static folder before any request handlers.
app.use(express.static(path.resolve(__dirname, 'public')));
// Handles request to root only.
app.get('/', (req, res) => {
// If you needed to modify the status code and content type, you would do so
// using the Express API, like so. However, this isn't necessary here; Express
// handles this automatically.
res.status(200);
res.type('text/html');
// Use sendFile(absPath) rather than sendfile(path), which is deprecated.
res.sendFile(path.resolve(__dirname, 'index.html'));
});
// Call the listen() method on your app rather than using Node's http module.
app.listen(PORT, (err) => {
if (err) throw err;
else console.log(`Listening on port ${PORT}`);
});