node.js TypeError: путь должен быть абсолютным или указать корень для res.sendFile [не удалось проанализировать JSON]

152

[add] Итак, моя следующая проблема - когда я пытаюсь добавить новую зависимость (npm install --save socket.io). Файл JSON также действителен. Я получаю эту ошибку: не удалось проанализировать 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 

Итак, я пытался выяснить, почему эта ошибка возвращалась. Все файлы (HTML, JSON, JS) находятся в одной папке на моем рабочем столе. Я использую node.js и socket.io

Это мой файл 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');
});

Вот что возвращается:

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
источник

Ответы:

331

Ошибка довольно очевидна, вам нужно указать абсолютный (а не относительный) путь и / или установить rootв объекте конфигурации для res.sendFile(). Примеры:

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

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

или укажите корень (который используется в качестве базового пути для первого аргумента res.sendFile():

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

Указание rootпути более полезно, когда вы передаете сгенерированный пользователем путь к файлу, который потенциально может содержать искаженные / вредоносные части, например ..(например ../../../../../../etc/passwd). Установка rootпути предотвращает использование таких вредоносных путей для доступа к файлам за пределами этого базового пути.

MSCDEX
источник
1
Каков наилучший способ указать корень как каталог?
SuperUberDuper
1
@SuperUberDuper Ты имеешь в виду как path.resolve(__dirname, '.../public')? Это преобразуется в подкаталог public в родительский каталог скрипта.
mscdex
прохладный! это навсегда сохранит это значение в __dirname в будущем?
SuperUberDuper
1
Привет, я попробовал следующее res.sendFile (path.resolve (__dirname + '/index.html', '../')), но получил сообщение: Cannot GET /
SuperUberDuper
2
@SuperUberDuper <- у этого парня все было в порядке (по крайней мере, для меня). Он использует функцию разрешения, которая нормализует пути, позволяя вам перемещаться с ../../<etc>синтаксисом типа. Обратите внимание на запятую между __dirnameи ../public. Использование знака + не работает.
Хельзгейт
20

Попробуйте добавить корневой путь.

app.get('/', function(req, res) {
    res.sendFile('index.html', { root: __dirname });
});
keeri
источник
12

в файлах .mjs у нас пока нет __dirname

следовательно

res.sendFile('index.html', { root: '.' })
Элиас Госс
источник
Это хорошее решение сработало для меня, так как мое требование состояло в том, чтобы вернуться после получения пути через __dirname. Поэтому я дал res.sendFile ('index.html', {root: './public/views'});
Нилаканта Сингх Део
для SITEMAP.XML в handelbars это правильное решение. Большое спасибо
titoih
3

Если вы доверяете пути, опция path.resolve:

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'));
    });
Майкл Коул
источник
3

Ошибка довольно проста. Скорее всего, причина в том, что ваш файл index.html не находится в корневом каталоге.

Или, если он находится в корневом каталоге, то относительная ссылка не работает.

Так что вам нужно сообщить серверу точное местоположение вашего файла. Это можно сделать с помощью метода dirname в NodeJs. Просто замените ваш код следующим:

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

Убедитесь, что вы добавили символ косой черты "/" перед вашей домашней страницей. В противном случае ваш путь станет следующим: rootDirectoryindex.html

В то время как вы хотите, чтобы это было: rootDirectory / index.html

saadi123
источник
1

Я решаю это с помощью переменной пути. Пример кода будет выглядеть ниже.

var path = require("path");

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname + '/index.html'));
})
Менука Ишан
источник
0

Если вы работаете с корневым каталогом, то вы можете использовать этот подход

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

но если вы используете маршруты, которые находятся внутри папки, скажем, /Routes/someRoute.jsвам нужно будет сделать что-то вроде этого

const path = require("path");
...
route.get("/some_route", (req, res) => {
   res.sendFile(path.resolve('FOLDER_IN_ROOT_DIRECTORY/index.html')
});
М. Сулеман Хан
источник
0

В Typescript с относительным путем к значку:

import path from 'path';

route.get('/favicon.ico', (_req, res) => res.sendFile(path.join(__dirname, '../static/myicon.png')));
Дэвид Дехган
источник
0

Он будет перенаправлять в index.html при вызове localhost: 8080.

app.get('/',function(req,res){
    res.sendFile('index.html', { root: __dirname });
});
Нагнат Мунгаде
источник
0

Я использовал приведенный ниже код и попытался показать файл sitemap.xml

router.get('/sitemap.xml', function (req, res) {
    res.sendFile('sitemap.xml', { root: '.' });
});
Хасан Батухан Курт
источник
-1

Это может быть решено другим способом:

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

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

});

process.env.PWD при запуске процесса будет добавлен рабочий каталог.

Абхишек Сахарн
источник
-2

Я сделал это, и теперь мое приложение работает нормально,

res.sendFile('your drive://your_subfolders//file.html');
user10310158
источник
Это плохая практика - жестко задавать местоположение файла. Если вы развернете приложение на другом компьютере, путь к файлу, скорее всего, будет другим
Мерве Сахин
-3

Вы можете рассмотреть возможность использования двойной косой черты в вашем каталоге, например

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

Ричард Мбинги
источник