Can you download files from a server with RESTApi - node.js

I was wondering if you can call create a GET request on a RESTApi server to download a file. For example if i called a GET request to http://<IP>/storage/download/:filePath/ it would download that file. I am writing the RESTAPi in nodejs.
const express = require('express');
const router = express.Router();
const fs = require('fs');
const path = require('path');
const root = {}
//for this example say filepath = api%2Fstorage%2FImages%2FtestPhoto.png or api/storage/Images/testPhoto.png
router.get("/download/:filePath", (req, res, next) => {
var filePath = req.params.filePath;
filePath = decodeURIComponent(filePath)
res.sendFile(filePath);
// this is what im questioning. If i use this will it send the file? if so how will i download it on the front end?
})

Yes. If the server directory is this
main.js
└── storage
└── Image
└── testPhoto.png
Add this,
router.use('/api/storage', express.static('storage'));
Then request it from frontend. GET /api/storage/Image/testPhoto.png

Express has a helper for this to make life easier.
app.get('/download', function(req, res){
const file = `${__dirname}/folder/download.csv`;
res.download(file); // Set disposition and send it.
});

Related

How to request a csv file from a url via nodejs?

I'm looking for a way to request a csv file from any url to save it then. If possible only using fs, http, request and express modules.
For testing I tried it with
request('http://localhost:3000/data1.csv').pipe(fs.createWriteStream('data2.csv'))
but i always get as a resonse (data2.csv)
<pre>Cannot GET /data1.csv</pre>
Simplified Code
const fs = require('fs')
const request = require('request')
const express = require('express')
const app = express()
app.listen(3000)
app.get('/download', (req, res) => {
request('http://localhost:3000/data1.csv').pipe(fs.createWriteStream('data2.csv'))
})
The file data1.csv is saved in the root of my project folder. But is this also the root of my nodejs server from where I started it?
What I'm doing wrong here?
Thanks!
You need to have an explicit handler that returns data1.csv:
app.get('/data1.csv', (req, res) => {
res.sendFile('data1.csv');
});

NodeJS: Files only update after restarting the express server

I am using nodejs with express for a small backend application which just returns a json file from another directory.
Example scenario:
My json files are in the directory "/var/data", so e.g. "/var/data/hello.json". If I start the nodejs backend with "node index.js" everything works as expected.
But if I change the contents of a json file, I still get the old version from the backend.
How can I set this up, so that my backend nodejs server detects these file changes in another directory without restarting it?
index.js:
const express = require('express');
const fs = require('fs');
const app = express();
app.use(express.json());
const myDataPath = "/var/data/";
app.get("/:id", (request, response) => {
let id = request.params.id;
let path = myDataPath + id + ".json";
if (fs.existsSync(path)) {
response.json(require(path));
} else {
response.sendStatus(404);
}
});
Issue is likely with using "require", this is a guess, but maybe require doesn't run twice for optimization reasons.
const express = require('express');
const fs = require('fs');
const app = express();
app.use(express.json());
const myDataPath = './var/data/';
app.get('/:id', (request, response) => {
let id = request.params.id;
let path = myDataPath + id + '.json';
console.log(path);
if (fs.existsSync(path)) {
response.json(JSON.parse(fs.readFileSync(path)));
} else {
response.sendStatus(404);
}
});
app.listen(1025);
The above code snippet worked on my testing example, I used readFileSync to retrieve the data, uncached, and the response changes when the file is modified, without needing to restart the app.

How to structure Express server to use granular API endpoints

I currently have an Express server I'm using for a mobile app which is structured as follows (server.js):
const PostRouter = require('./api/production/Post');
const UserRouter = require('./api/production/User');
...
app.use('/posts', PostRouter)
app.use('/users', UserRouter)
and then in api/production/Post I have:
router.get('/fetch', (req, res) => {
...
}
router.get('/delete', (req, res) => {
...
}
etc..
However, I would really like to rebuild the server to match the structure of my corresponding NextJS app and its API structure, which would be something like:
/api/posts/
add-post/
index.js
fetch-all/
index.js
edit-post/
index.js
Where each index.js file contains just one endpoint/query instead of the current structure where each file has multiple queries with the router.get thing.
It looks like this is possible by creating a Router for each endpoint with something like:
const PostFetchAllRouter = require('./api/posts/fetch-all');
const PostEditPostRouter = require('./api/posts/edit-post');
...
app.use('posts/fetch-all', PostFetchAllRouter)
app.use('posts/edit-post', PostEditPostRouter)
What would be the best way to do this, please? Is there an easier way to do this without all the boilerplate in the server.js file? I'm very new to Express - please excuse if it's a naive question
You could move the "boilerplate" code to the different router files and build a router chain. But you have to write a little bit more.
server.js
|-api/
|--posts/
|---PostsRouter.js
|---fetchAll.js
|--users/
|---UserRouter.js
fetchAll.js
const express = require("express");
const FetchAll = express.Router();
FetchAll.get("/fetch", (req, res) => { res.send("/posts/fetch") });
module.exports = FetchAll;
PostsRouter.js
const express = require("express");
const FetchAll = require("./fetchAll");
const PostsRouter = express.Router();
PostsRouter.use(FetchAll);
module.exports = PostsRouter;
server.js
const express = require('express');
const PostsRouter = require("./api/posts/PostsRouter");
let app = express();
app.use("/posts", PostsRouter);
app.listen(80, () => {});
If you build it like that you would plug the small routers into the next bigger one and then use them in the server.js.
GET localhost/posts/fetch HTTP/1.1
// returns in my example the string "/posts/fetch"
Is that what you were looking for?

require() in node.js is not working and returns error?

I have looked through stackoverflow and read about require. However I cannot understand why my require function does not run.
app.js code:
var http = require('http');
var express = require("express");
var app = express();
//Twitter Search -------------------
app.get("/tweet, function(req,res){
var twiter = require('twiter.js');
});
app.listen(3000);
twitter.js code:
console.log("twitter.js ran");
Make sure both app.js and twitter.js in same directory
And add ./ before it. Just use following
var twitter = require('./twitter'); // .js extension is not necessary
Also as alexey mentioned. twiter is not same as twitter :)
Take care of your typos. (I think I'm too lazy to read it carefully)
app.js
var http = require('http');
var express = require("express");
var app = express();
//Twitter Search -------------------
app.get("/tweet", function (req, res) {
var twitter = require('./twitter');
twitter.log();
});
app.listen(3000);
twitter.js should be exposed using module.exports
var twitter = {
log: function () {
console.log('twitter is loaded');
}
};
module.exports = twitter;
This should now print "twitter is loaded" in your console, when you visit localhost:3000/tweet

How to modularize routing with Node.js Express

I'm building a web app with Express and Node and am trying to factor my routing so that I don't have hundreds of routes in the same file. This site serves different files within the projects directory, so I made a file in routes/ called projectRoutes.jsto handle the routing for project files:
var express = require('express');
module.exports = function() {
var functions = {}
functions.routeProject = function(req, res) {
res.render('pages/projects/' + req.params.string, function(err, html) {
if (err) {
res.send("Sorry! Page not found!");
} else {
res.send(html);
}
});
};
return functions;
}
Then, in my routes.js, I have this...
var projectRoutes = require("./projectRoutes");
router.get('/projects/:string', function(req, res) {
projectRoutes().routeProject(req, res);
});
Is there a better way to structure this functionality within projectRoutes.js? In other words, how can I configure projectRoutes.js so that I can write the follow line of code in index.js:
router.get('/projects/:string', projectRoutes.routeProject);
The above seems like the normal way to handle something like this, but currently the above line throws an error in Node that says the function is undefined.
Thanks for your help!
You should use the native express router, it was made to solve this exact problem! It essentially lets you create simplified nested routes in a modular way.
For each of your resources, you should separate out your routes into several modules named <yourResource>.js. Those modules would contain all of the routing code as well as any other configuration or necessary functions. Then you would attach them in index.js with:
var apiRoute = router.route('/api')
apiRoute.use('/< yourResource >', yourResourceRouter)
For example, if you had a resource bikes:
In index.js:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes')
apiRoute.use('/bikes', bikeRoutes)
Then in bike.js:
var express = require('express')
, router = express.Router()
, bikeRoutes = router.route('/')
bikeRoutes.get(function (req, res) {
res.send('api GET request received')
});
module.exports = bikeRoutes
From there its easy to see that you can build many different resources and continually nest them.
A larger of example of connecting the routes in index.js would be:
var apiRoute = router.route('/api')
, bikeRoutes = require('./bikes')
, carRoutes = require('./cars')
, skateboardRoutes = require('./skateboards')
, rollerskateRoutes = require('./rollerskates')
// routes
apiRoute.use('/bikes', bikeRoutes)
apiRoute.use('/cars', carRoutes)
apiRoute.use('/skateboards', skateboardRoutes)
apiRoute.use('/rollerskates', rollerskateRoutes)
Each router would contain code similar to bikes.js. With this example its easy to see using express's router modularizes and makes your code base more manageable.
Another option is to use the Router object itself, instead of the Route object.
In Index.js:
//Load Routes
BikeRoutes = require('./routes/Bike.js');
CarRoutes = require('./routes/Car.js');
//Routers
var express = require('express');
var ApiRouter = express.Router();
var BikeRouter = express.Router();
var CarRouter = express.Router();
//Express App
var app = express();
//App Routes
ApiRouter.get('/Api', function(req, res){...});
ApiRouter.use('/', BikeRouter);
ApiRouter.use('/', CarRouter);
In Bike.js:
var express = require('express');
var router = express.Router();
router.get('/Bikes', function(req, res){...});
module.exports = router;
Similarly in Car.js

Resources