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)

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.


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 });
});

12

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

conseqüentemente

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

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'));
    });

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


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'));
})

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')
});

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')));

0

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

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

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: '.' });
});

-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.


-2

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

res.sendFile('your drive://your_subfolders//file.html');

É 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')
})

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.