node.js TypeError: o caminho deve ser absoluto ou especificar raiz para res.sendFile [falhou ao analisar JSON]

150

[add] Então, meu próximo problema é que, quando tento adicionar uma nova dependência (npm install --save socket.io). O arquivo JSON também é válido. Eu recebo este erro: Falha ao analisar 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 

Então, eu tenho tentado descobrir por que esse erro está retornando. Todos os arquivos (HTML, JSON, JS) estão dentro da mesma pasta na minha área de trabalho. Estou usando node.js e socket.io

Este é o meu arquivo 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');
});

É isso que está sendo retornado:

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
fonte

Respostas:

331

O erro é bastante claro, você precisa especificar um caminho absoluto (em vez de relativo) e / ou definido rootno objeto de configuração para res.sendFile(). Exemplos:

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

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

ou especifique uma raiz (que é usada como o caminho base para o primeiro argumento res.sendFile():

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

A especificação do rootcaminho é mais útil quando você está passando um caminho de arquivo gerado pelo usuário que pode conter partes malformadas / mal-intencionadas, como ..(por exemplo ../../../../../../etc/passwd). Definir o rootcaminho impede que esses caminhos maliciosos sejam usados ​​para acessar arquivos fora desse caminho base.

mscdex
fonte
1
qual é a melhor maneira de especificar a raiz como sendo uma dir?
SuperUberDuper
1
@SuperUberDuper Você quer dizer path.resolve(__dirname, '.../public')? Isso resolverá o subdiretório 'public' do diretório pai do script.
Mscdex
legal! isso armazena permanentemente esse valor em __dirname no futuro?
SuperUberDuper
1
Oi, eu tentei o seguinte res.sendFile (path.resolve (__ dirname + '/index.html', '../')) mas obtive a mensagem: Não é possível obter /
SuperUberDuper
2
@SuperUberDuper <- esse cara estava certo (pelo menos para mim). Ele está usando a função de resolução que normaliza os caminhos, permitindo que você navegue pela ../../<etc>sintaxe do tipo. Observe a vírgula entre __dirnamee ../public. Usar um sinal de + não funciona.
precisa saber é o seguinte
20

Tente adicionar o caminho raiz.

app.get('/', function(req, res) {
    res.sendFile('index.html', { root: __dirname });
});
keeri
fonte
12

em arquivos .mjs que, por enquanto, não temos __dirname

conseqüentemente

res.sendFile('index.html', { root: '.' })
Elias Goss
fonte
Essa é uma boa solução que funcionou para mim, pois meu requisito era voltar depois de obter o caminho através de __dirname. Então, dei res.sendFile ('index.html', {root: './public/views'});
Nilakantha singh deo
para SITEMAP.XML nas barras manuais, esta é a solução certa. Muito obrigado
titoih
3

Se você confia no caminho, path.resolve é uma opção:

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
fonte
3

O erro é bastante direto. Provavelmente, o motivo é que o arquivo index.html não está no diretório raiz.

Ou, se estiver no diretório raiz, a referência relativa não está funcionando.

Então, você precisa informar ao servidor a localização exata do seu arquivo. Isso pode ser feito usando o método dirname nos NodeJs. Apenas substitua seu código por este:

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

Certifique-se de adicionar o símbolo de barra "/" antes da sua página inicial. Caso contrário, seu caminho se tornará: rootDirectoryindex.html

Considerando que você deseja que seja: rootDirectory / index.html

saadi123
fonte
1

Eu resolvo isso usando a variável path. O código de exemplo será parecido abaixo.

var path = require("path");

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname + '/index.html'));
})
Menuka Ishan
fonte
0

Se você estiver trabalhando no diretório raiz, poderá usar esta abordagem

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

mas se você estiver usando rotas dentro de uma pasta, digamos /Routes/someRoute.jsque será necessário fazer algo assim

const path = require("path");
...
route.get("/some_route", (req, res) => {
   res.sendFile(path.resolve('FOLDER_IN_ROOT_DIRECTORY/index.html')
});
M.suleman Khan
fonte
0

Em Texto datilografado com caminho relativo para o ícone:

import path from 'path';

route.get('/favicon.ico', (_req, res) => res.sendFile(path.join(__dirname, '../static/myicon.png')));
David Dehghan
fonte
0

Ele será redirecionado para index.html na chamada localhost: 8080.

app.get('/',function(req,res){
    res.sendFile('index.html', { root: __dirname });
});
Nagnath Mungade
fonte
0

Usei o código abaixo e tentei mostrar o arquivo sitemap.xml

router.get('/sitemap.xml', function (req, res) {
    res.sendFile('sitemap.xml', { root: '.' });
});
Hasan Batuhan Kurt
fonte
-1

Isso pode ser resolvido de outra maneira:

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

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

});

process.env.PWD precederá o diretório de trabalho quando o processo foi iniciado.

Abhishek saharn
fonte
-2

Eu fiz isso e agora meu aplicativo está funcionando corretamente,

res.sendFile('your drive://your_subfolders//file.html');
user10310158
fonte
É uma prática recomendada codificar permanentemente o local do arquivo. Se você implantar o aplicativo em uma máquina diferente, o caminho do arquivo provavelmente será diferente
Merve Sahin
-3

Você pode considerar o uso de barras duplas no seu diretório, por exemplo

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

Richard Mbingi
fonte