in the question below, someone has given me the following code:
res.end(fs.readFileSync(__dirname + "index.html"));
However this is creating a filename of folderNameindex.html, i.e. there needs to be a backslash before index.html. From googling, the solution should be two x \ within the double quotes, resulting in "\index.html". I've tried this and many other variations, single, double, treble, forward slashes, regex escaping. In every case, my CLI tells me it cannot find file folderNameindex.html.
This is probably simple. Grateful for any help.
Can i use node as webserver for html app?
EDIT:
My new code:
const http = require('http'), // to listen to http requests
path = require('path'),
fullPath = path.join(__dirname, 'index.html'),
fs = require('fs'); // to read from the filesystem
const app = http.createServer((req,res) => {
// status should be 'ok'
res.writeHead(200);
// read index.html from the filesystem,
// and return in the body of the response
res.end(fs.readFileSync(fullPath)); });
app.listen(3000); // listen on 3000
I still get the same error - my command line tells me it can't find folderNameindex.html
You should use path.join, for example;
const path = require('path')
const fullPath = path.join(__dirname, 'index.html')
Additionally, there are many other functions that will help you working with paths in a portable way, make sure to read all the docs for the path and file system module.
Related
this is my first question here. I need some help with my code structure. My api in node with express have to do the following:
receipt GET /api/file/{filename}
return the file content, its could be a big one (a few GB).
For now, I could get the files with streams, but I don't the best practice to handle error in this case.
'use strict';
const fs = require('fs');
const express = require('express');
const app = express();
const path = require('path');
const filePath = path.join(__dirname, `../file`);
console.log(filePath)
app.get('/api/:filename', (req, res) => {
let filename = req.params.filename
const streamFile = fs.createReadStream(`${filePath}/${filename}`);
streamFile.pipe(res);
} );
module.exports = app;
Should I make another dir, maybe 'modules', and there code an async function to read and pipe the files, and call the function from app.get in routes dir ?
Remember that Express is an "un-opinionated, minimalist web framework for Node.js applications", unopinionated means that it doesn't decide for you a lot of aspects of what tool you use for each specific task, and that is the main difference with another frameworks like Rails. Said that, you could use the classical and and old try and catch, in this case around your I/O operation. A module is a way to mantain separation of concerns and it's a way to organize your code so you can fastly identify what is the part of your code that is causing a malfunction. So in this case i don't consider it necessary because your router's callback is doing one thing and that is ok.
app.get('/api/:filename', (req, res) => {
let filename = req.params.filename
try{
const path = `${filePath}/${filename}`;
if (!fs.existsSync(path)) return res.status(404).send('You could send any message here...');
const streamFile = fs.createReadStream(path);
streamFile.pipe(res);
} catch {
res.status(500).send();
};
});
This question already has answers here:
What is the difference between __dirname and ./ in node.js?
(2 answers)
Closed 3 years ago.
I created a file called nodes, then initialized the file with npm init and the main js file is called main.js. I also created index.html and index.css in the file, after that I want to use Node.js Render this index.html, so I wrote in main.js:
const http = require('http');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 9000;
const mainHTML = './index.html';
const server = http.createServer((req, res) => {
fs.stat(`./${mainHTML}`, (err, stats) => {
if(stats) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
fs.createReadStream(mainHTML).pipe(res);
}
});
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
I opened the server with the node desktop/nodes command, but node.js could not find the file.
Until I changed the relative path to an absolute path, Node.js will recognize it:
const mainHTML = 'desktop/nodes/index.html';
Why is this? If I want to use a relative path, how do I do it?
When you access a file in node.js with a relative path, the file is accessed relative to the value of the current working directory for the process. Note, in the modular world of node.js, the current working directory may or may not be the same as the directory where your module was located. And, your code can change the current working directory to be whatever you want it to be.
It is common in modular node.js code to have a programming desire to access things relative to the directory where the current module's code was loaded from. This gives you the ability to use relative paths so the app/module can work anywhere, but it gives you certainty that you'll get the files you want. To do this, one typically uses the module-specific variable __dirname. This is the directory that the current module was loaded from. If it's the main script that node.js was started with then, it's the directory of that script.
So, to get a file from the same directory as the script you are current in, you would do this:
const mainHTML = 'index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
To access a file in a subdirectory public below where the script is, you could do this:
const mainHTML = 'public/index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
To access a file in a different subdirectory at the same level (common parent directory) as where the script is, you could do this:
const mainHTML = '../public/index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
All of these use paths that are relative to where the script itself is located and do not depend upon how the module/script was loaded or what the current working directory of the app is.
You are creating http server, which creates it's path as base, so it understands only paths taking that base path as relative path. If you want to use relative path, then you need to resolve that path.
You can use 'path' library.
const path = require('path')
// To resolve parent path
path.resolve('..', __dirname__)
I want to read a symlink, and get the details of the link itself, not the contents of the linked file. How do I do that in Node, in a cross-platform way?
I can detect symlinks easily using lstat, no problem. Once I know the path of the file, and that it is a symlink though, how can I read it? fs.readFile always reads the target file, or throws an error for reading a directory for links to directories.
There is a fs.constants.O_SYMLINK constant, which in theory solves this on OSX, but it seems to be undefined on both Ubuntu & Windows 10.
If you have determined that the file is a symlink try this:
fs.readlink("./mysimlink", function (err, linkString) {
// .. do some error handling here ..
console.log(linkString)
});
Confirmed as working on Linux.
You could then use fs.realpath() to turn it into a full path. Be aware though that linkString can be just a filename or relative path as well as a fully qualified path so you may have to get fs.realpath() for the symlink, determine its directory part and prefix it to linkString before using fs.realpath() on it.
I've just faced the same issue: sometimes fs.readlink returns a relative path, sometimes it returns an absolute path.
(proper error handling not implemented to keep things simple)
const fs = require('fs');
const pathPckg = require('path');
async function getTarLinkOfSymLink(path){
return new Promise((resolve, reject)=>{
fs.readlink(path, (err, tarPath)=>{
if(err){
console.log(err.message);
return resolve('');
}
const baseSrcPath = pathPckg.dirname(path);
return resolve( pathPckg.resolve(baseSrcPath, tarPath) );
});
});
}
// usage:
const path = '/example/symbolic/link/path';
const tarPath = await getTarLinkOfSymLink(path);
The code works if the symbolic link is either a file or a directory/folder - tested on Linux
I'm trying to get my express to serve up static files that are in another location:
This is the current directory I have:
|__client
| |__thumbnails.html
|
|__server
|__app.js
I tried to just use app.use(express.static(path.join(__dirname, '..', 'client')));, but it wouldn't serve the file at all. However, when I used the same path.join for a get request on '/' it will send the file.
Here it the code I have at the moment. It's working, thank God, but I want to see if there is a way for me to serve it without actually sending the file.
const express = require('express');
const path = require('path');
const similar = require('./routes/similar');
const image = require('./routes/images');
const app = express();
app.use(express.static(path.join(__dirname, '..', 'client')));
app.use('/item', similar);
app.use('/thumbnail', image);
app.get('/', (req, res) => res.status(200).sendFile(path.join(__dirname, '..', 'client', 'thumbnail.html')));
module.exports = app;
You can make the file anything you want, through configuration of the serve-static module:
https://expressjs.com/en/resources/middleware/serve-static.html
From that page:
var express = require('express')
var serveStatic = require('serve-static')
var app = express()
app.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}))
app.listen(3000)
now anything that you put in the 'index' array will be looked at, in the order you defined.
Otherwise, you would still be able to get to your html file if you put the actual filename in the url.
Okay I think I figured it out. So apparently you have to have the html saved as index. Express is looking for that, but since I don't have an index.html it skips my thumbnails.html.
So renaming my html to index.html fixed the issue.
UPDATE:
So reading through the documentation, you can set the what the default is by passing in an options. I passed in { index: 'thumbnails.html' } as the second argument for static and it serves my html.
How do I write this to go back up the parent 2 levels to find a file?
fs.readFile(__dirname + 'foo.bar');
Try this:
fs.readFile(__dirname + '/../../foo.bar');
Note the forward slash at the beginning of the relative path.
Use path.join http://nodejs.org/docs/v0.4.10/api/path.html#path.join
var path = require("path"),
fs = require("fs");
fs.readFile(path.join(__dirname, '..', '..', 'foo.bar'));
path.join() will handle leading/trailing slashes for you and just do the right thing and you don't have to try to remember when trailing slashes exist and when they dont.
I know it is a bit picky, but all the answers so far are not quite right.
The point of path.join() is to eliminate the need for the caller to know which directory separator to use (making code platform agnostic).
Technically the correct answer would be something like:
var path = require("path");
fs.readFile(path.join(__dirname, '..', '..', 'foo.bar'));
I would have added this as a comment to Alex Wayne's answer but not enough rep yet!
EDIT: as per user1767586's observation
The easiest way would be to use path.resolve:
path.resolve(__dirname, '..', '..');
Looks like you'll need the path module. (path.normalize in particular)
var path = require("path"),
fs = require("fs");
fs.readFile(path.normalize(__dirname + "/../../foo.bar"));
If another module calls yours and you'd still like to know the location of the main file being run you can use a modification of #Jason's code:
var path = require('path'),
__parentDir = path.dirname(process.mainModule.filename);
fs.readFile(__parentDir + '/foo.bar');
That way you'll get the location of the script actually being run.
If you not positive on where the parent is, this will get you the path;
var path = require('path'),
__parentDir = path.dirname(module.parent.filename);
fs.readFile(__parentDir + '/foo.bar');
You can use
path.join(__dirname, '../..');
this will also work:
fs.readFile(`${__dirname}/../../foo.bar`);
i'm running electron app and i can get the parent folder by path.resolve()
parent 1 level:path.resolve(__dirname, '..') + '/'
parent 2 levels:path.resolve(__dirname, '..', '..') + '/'
This works fine
path.join(__dirname + '/../client/index.html')
const path = require('path')
const fs = require('fs')
fs.readFile(path.join(__dirname + '/../client/index.html'))
You can locate the file under parent folder in different ways,
const path = require('path');
const fs = require('fs');
// reads foo.bar file which is located in immediate parent folder.
fs.readFile(path.join(__dirname, '..', 'foo.bar');
// Method 1: reads foo.bar file which is located in 2 level back of the current folder.
path.join(__dirname, '..','..');
// Method 2: reads foo.bar file which is located in 2 level back of the current folder.
fs.readFile(path.normalize(__dirname + "/../../foo.bar"));
// Method 3: reads foo.bar file which is located in 2 level back of the current folder.
fs.readFile(__dirname + '/../../foo.bar');
// Method 4: reads foo.bar file which is located in 2 level back of the current folder.
fs.readFile(path.resolve(__dirname, '..', '..','foo.bar'));