Download file with app.get problem
-
Hello !
I have a file (among others) in a specific folder outside of nodebb (for example /toto/myfiles/filetoget ; nodebb executable is in /toto/nodebb folder).
I want to be able to download the /toto/myfiles/filetoget file with the route "/myfiles/filetoget". For this, I use the following code (in the static:app.load hook) in a plugin :
app.get('/myfiles/:file(*?)', function (req, res) { // absolute path to the file to get var absolutefile = path.dirname(process.cwd()) + '/myfiles/' + req.params.file; if (fs.existsSync(absolutefile)) { res.status(200); res.sendFile(absolutefile); } else { console.log('File not found'); res.status(404); res.render('404', {path: req.path}); } });
It works when I full load page http://127.0.0.1:4567/myfiles/filetoget but it doesn't work when I click on a link with 'myfiles/filetoget' (showing also the full address http://127.0.0.1:4567/myfiles/filetoget on a nodebb page). I have a page of nodebb saying the page is not found and there is no particular message in the console.
How can I solve this problem ? (I do this because I will do other things (permissions...) before the download of the file in my plugin).
I will also link these files in admin/manage/categories/** as external link (I hope it's possible)...
If I use a wrong way, how can I make relative links (routes) in nodebb to files outer from nodebb folder ?
Thanks in advance for help !
-
NodeBB probably treats that url like a normal page since it doesn't start with
/uploads
or/assets/uploads
and it tries to ajaxify to that page. https://github.com/NodeBB/NodeBB/blob/master/public/src/ajaxify.js#L395You also have to be careful with allowing access to the filesystem and make sure users can only download from the myfiles folder. Ie if someone manages to pass in
req.params.file = ../nodebb/config.json
they might download your config.json file. -
@baris said in Download file with app.get problem:
NodeBB probably treats that url like a normal page since it doesn't start with
/uploads
or/assets/uploads
and it tries to ajaxify to that page. https://github.com/NodeBB/NodeBB/blob/master/public/src/ajaxify.js#L395So is there a way to prevent this or another way to do what I want ? I need to make links to files that are not in nodebb folder (I don't want users to be able to directly download them like when they are in public/uploads because I will check some specific permissions before...). Note also that files will change so it must work without restarting nodebb...
You also have to be careful with allowing access to the filesystem and make sure users can only download from the myfiles folder. Ie if someone manages to pass in
req.params.file = ../nodebb/config.json
they might download your config.json file.Yes. It will be a part of my plugin.
-
@julian said in Download file with app.get problem:
I would look into using express.static to mount a directory and have it accessible as a route.
I will give it a try but will it prevent the ajaxify problem raised by @baris at the begining of its answer ?
Also, files will not be public ? I want to serve files only after tests of permissions...
-
Finally, I made it simpler...
I made a link from /toto/myfiles to public/uploads/myfiles. Then, I wrote this app.get code in my plugin :
app.get('/uploads/myfiles/:file(*?)', function (req, res) { // Things TODO with req.params.file for permissions (after work on it)... var longfilename = path.resolve('public' + req.url); if (fs.existsSync(longfilename)) { res.status(200); res.sendFile(longfilename); } else { console.log('Fichier non trouvé'); res.status(404); res.render('404', {path: req.path}); } });
Now, there is no problem with the ajaxify thing... Ouf !
I'm going to open another topic for another question about the 404 error rendering...