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)

답변:


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경로를 설정 하면 이러한 악성 경로가 해당 기본 경로 외부의 파일에 액세스하는 데 사용되지 않습니다.


1
루트를 디렉토리로 지정하는 가장 좋은 방법은 무엇입니까?
SuperUberDuper 2016 년

1
@SuperUberDuper 다음과 같은 의미 path.resolve(__dirname, '.../public')입니까? 스크립트의 상위 디렉토리의 'public'서브 디렉토리로 분석됩니다.
mscdex

멋있는! 향후 __dirname에이 값을 영구적으로 저장합니까?
SuperUberDuper

1
안녕하세요, 다음 res.sendFile (path.resolve (__ dirname + '/index.html', '../')) 시도했지만 메시지가 표시되지 않습니다 : GET /
SuperUberDuper

2
@SuperUberDuper <-이 사람이 옳았습니다 (적어도 저에게는). 그는 경로를 정규화하는 resolve 함수를 사용하여 ../../<etc>유형 구문 으로 탐색 할 수 있습니다 . __dirname와 사이에 쉼표가 ../public있습니다. + 부호를 사용하면 작동하지 않습니다.
Helzgate

20

루트 경로를 추가하십시오.

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

12

.mjs 파일에는 현재 __dirname이 없습니다.

그 후

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

__dirname을 통해 경로를 얻은 후 되돌아가는 것이 좋았으므로 res.sendFile ( 'index.html', {root : './public/views'});
nilakantha singh deo

handelbars의 SITEMAP.XML의 경우 이것이 올바른 솔루션입니다. 대단히 감사합니다
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 파일이 루트 디렉토리에 없기 때문입니다.

또는 루트 디렉토리에 있으면 상대 참조가 작동하지 않습니다.

따라서 서버에게 파일의 정확한 위치를 알려 주어야합니다. NodeJ에서 dirname 메소드를 사용하여 수행 할 수 있습니다. 코드를 다음과 같이 바꾸십시오.

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

홈페이지 앞에 슬래시 "/"기호를 추가해야합니다. 그렇지 않으면 경로는 rootDirectoryindex.html이됩니다.

원하는 경우 : rootDirectory / index.html


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

localhost : 8080 호출에서 index.html로 리디렉션됩니다.

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

파일 위치를 하드 코딩하는 것은 좋지 않습니다. 응용 프로그램을 다른 컴퓨터에 배포하면 파일 경로가 다를 수 있습니다.
Merve Sahin

-3

디렉토리에 이중 슬래시를 사용하는 것을 고려할 수 있습니다.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.