node.js TypeError: ścieżka musi być bezwzględna lub określać root do res.sendFile [nie udało się przeanalizować JSON]

152

[dodaj] Więc moim następnym problemem jest to, że kiedy próbuję dodać nową zależność (npm install --save socket.io). Plik JSON jest również prawidłowy. Pojawia się ten błąd: nie udało się przeanalizować pliku JSON

npm ERR! Unexpected string
npm ERR! File: /Users/John/package.json
npm ERR! Failed to parse package.json data.
npm ERR! package.json must be actual JSON, not just JavaScript.
npm ERR! 
npm ERR! This is not a bug in npm.
npm ERR! Tell the package author to fix their package.json file. JSON.parse 

Próbowałem więc dowiedzieć się, dlaczego ten błąd powraca. Wszystkie pliki (HTML, JSON, JS) znajdują się w tym samym folderze na moim pulpicie. Używam node.js i socket.io

To jest mój plik JS:

var app = require('express')();
var http = require('http').Server(app);

app.get('/', function(req, res){
  res.sendFile('index.html');
});

http.listen(3000,function(){
    console.log('listening on : 3000');
});

Oto, co jest zwracane:

MacBook-Pro:~ John$ node /Users/John/Desktop/Chatapp/index.js 
listening on : 3000
TypeError: path must be absolute or specify root to res.sendFile
    at ServerResponse.sendFile (/Users/John/node_modules/express/lib/response.js:389:11)
    at /Users/John/Desktop/Chatapp/index.js:5:7
    at Layer.handle [as handle_request] (/Users/John/node_modules/express/lib/router/layer.js:76:5)
    at next (/Users/John/node_modules/express/lib/router/route.js:100:13)
    at Route.dispatch (/Users/John/node_modules/express/lib/router/route.js:81:3)
    at Layer.handle [as handle_request] (/Users/John/node_modules/express/lib/router/layer.js:76:5)
    at /Users/John/node_modules/express/lib/router/index.js:234:24
    at Function.proto.process_params (/Users/John/node_modules/express/lib/router/index.js:312:12)
    at /Users/John/node_modules/express/lib/router/index.js:228:12
    at Function.match_layer (/Users/John/node_modules/express/lib/router/index.js:295:3)
TypeError: path must be absolute or specify root to res.sendFile
    at ServerResponse.sendFile (/Users/John/node_modules/express/lib/response.js:389:11)
    at /Users/John/Desktop/Chatapp/index.js:5:7
    at Layer.handle [as handle_request] (/Users/John/node_modules/express/lib/router/layer.js:76:5)
    at next (/Users/John/node_modules/express/lib/router/route.js:100:13)
    at Route.dispatch (/Users/John/node_modules/express/lib/router/route.js:81:3)
    at Layer.handle [as handle_request] (/Users/John/node_modules/express/lib/router/layer.js:76:5)
    at /Users/John/node_modules/express/lib/router/index.js:234:24
    at Function.proto.process_params (/Users/John/node_modules/express/lib/router/index.js:312:12)
    at /Users/John/node_modules/express/lib/router/index.js:228:12
    at Function.match_layer (/Users/John/node_modules/express/lib/router/index.js:295:3)
IE8IsBetterThenGoogleChrome
źródło

Odpowiedzi:

331

Błąd jest dość jasny, musisz określić bezwzględną (zamiast względnej) ścieżkę i / lub ustawić rootw obiekcie konfiguracyjnym dla res.sendFile(). Przykłady:

// assuming index.html is in the same directory as this script

res.sendFile(__dirname + '/index.html');

lub podaj katalog główny (który jest używany jako ścieżka podstawowa dla pierwszego argumentu do res.sendFile():

res.sendFile('index.html', { root: __dirname });

Określenie rootścieżki jest bardziej przydatne, gdy przekazujesz ścieżkę do pliku wygenerowaną przez użytkownika, która może potencjalnie zawierać zniekształcone / złośliwe części, takie jak ..(np ../../../../../../etc/passwd.). Ustawienie rootścieżki zapobiega wykorzystywaniu takich złośliwych ścieżek do uzyskiwania dostępu do plików spoza tej ścieżki podstawowej.

mscdex
źródło
1
Jaki jest najlepszy sposób określenia katalogu głównego jako katalogu?
SuperUberDuper
1
@SuperUberDuper Masz na myśli jak path.resolve(__dirname, '.../public')? To spowoduje przejście do podkatalogu „public” katalogu nadrzędnego skryptu.
mscdex
chłodny! czy to na stałe zapisze tę wartość w __dirname w przyszłości?
SuperUberDuper
1
Cześć, próbowałem następującego pliku res.sendFile (path.resolve (__ dirname + '/index.html', '../')), ale otrzymuję komunikat: Cannot GET /
SuperUberDuper
2
@SuperUberDuper <- ten facet miał rację (przynajmniej dla mnie). Używa funkcji rozwiązywania, która normalizuje ścieżki, umożliwiając nawigację za pomocą ../../<etc>składni typu. Zwróć uwagę na przecinek między __dirnamea ../public. Używanie znaku + nie działa.
Helzgate
20

Spróbuj dodać ścieżkę główną.

app.get('/', function(req, res) {
    res.sendFile('index.html', { root: __dirname });
});
keeri
źródło
12

w plikach .mjs, których na razie nie mamy __dirname

W związku z tym

res.sendFile('index.html', { root: '.' })
Elias Goss
źródło
To dobre rozwiązanie zadziałało dla mnie, ponieważ moim wymaganiem był powrót po uzyskaniu ścieżki przez __dirname. Więc dałem res.sendFile ('index.html', {root: './public/views'});
nilakantha singh deo
dla SITEMAP.XML w handlubarach jest to właściwe rozwiązanie. Dziękuję bardzo
titoih
3

Jeśli ufasz ścieżce, path.resolve jest opcją:

var path = require('path');

// All other routes should redirect to the index.html
  app.route('/*')
    .get(function(req, res) {
      res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
    });
Michael Cole
źródło
3

Błąd jest dość prosty. Najprawdopodobniej przyczyną jest to, że plik index.html nie znajduje się w katalogu głównym.

Lub jeśli znajduje się w katalogu głównym, odwołanie względne nie działa.

Musisz więc podać serwerowi dokładną lokalizację pliku. Można to zrobić za pomocą metody dirname w NodeJs. Po prostu zamień swój kod na ten:

 app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

Upewnij się, że dodałeś symbol ukośnika „/” przed stroną główną. W przeciwnym razie Twoja ścieżka będzie wyglądać następująco: rootDirectoryindex.html

Podczas gdy chcesz, aby był to katalog: rootDirectory / index.html

saadi123
źródło
1

Rozwiązuję to za pomocą zmiennej ścieżki. Przykładowy kod będzie wyglądał jak poniżej.

var path = require("path");

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname + '/index.html'));
})
Menuka Ishan
źródło
0

Jeśli pracujesz na katalogu głównym, możesz użyć tego podejścia

res.sendFile(__dirname + '/FOLDER_IN_ROOT_DIRECTORY/index.html');

ale jeśli używasz tras, które są w folderze, powiedzmy, /Routes/someRoute.jsże będziesz musiał zrobić coś takiego

const path = require("path");
...
route.get("/some_route", (req, res) => {
   res.sendFile(path.resolve('FOLDER_IN_ROOT_DIRECTORY/index.html')
});
M. Suleman Khan
źródło
0

W Typescript ze względną ścieżką do ikony:

import path from 'path';

route.get('/favicon.ico', (_req, res) => res.sendFile(path.join(__dirname, '../static/myicon.png')));
David Dehghan
źródło
0

Przekieruje do index.html na połączenie localhost: 8080.

app.get('/',function(req,res){
    res.sendFile('index.html', { root: __dirname });
});
Nagnath Mungade
źródło
0

Użyłem poniższego kodu i próbowałem wyświetlić plik sitemap.xml

router.get('/sitemap.xml', function (req, res) {
    res.sendFile('sitemap.xml', { root: '.' });
});
Hasan Batuhan Kurt
źródło
-1

Można to rozwiązać w inny sposób:

app.get("/", function(req, res){

    res.send(`${process.env.PWD}/index.html`)

});

process.env.PWD doda katalog roboczy na początku procesu.

Abhishek saharn
źródło
-2

Zrobiłem to i teraz moja aplikacja działa poprawnie,

res.sendFile('your drive://your_subfolders//file.html');
user10310158
źródło
Zakodowanie lokalizacji pliku na stałe jest złą praktyką. Jeśli wdrożysz aplikację na innym komputerze, najprawdopodobniej ścieżka do pliku będzie inna
Merve Sahin
-3

Możesz rozważyć użycie podwójnych ukośników w swoim katalogu, np

app.get('/',(req,res)=>{
    res.sendFile('C:\\Users\\DOREEN\\Desktop\\Fitness Finder' + '/index.html')
})

Richard Mbingi
źródło