node.js TypeError: path harus absolut atau tentukan root untuk res.sendFile [gagal mem-parse JSON]


152

[add] Jadi masalah saya berikutnya adalah ketika saya mencoba menambahkan ketergantungan baru (npm install --save socket.io). File JSON juga valid. Saya mendapatkan kesalahan ini: Gagal mengurai 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 

Jadi saya sudah mencoba mencari tahu mengapa kesalahan ini telah kembali. Semua file (HTML, JSON, JS) ada di dalam folder yang sama di desktop saya. Saya menggunakan node.js dan socket.io

Ini adalah file JS saya:

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

Inilah yang dikembalikan:

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)

Jawaban:


331

Kesalahannya cukup jelas, Anda perlu menentukan path absolut (bukan relatif) dan / atau mengatur rootobjek config untuk res.sendFile(). Contoh:

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

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

atau tentukan root (yang digunakan sebagai jalur dasar untuk argumen pertama ke res.sendFile():

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

Menentukan rootjalur lebih berguna ketika Anda melewati jalur file yang dibuat pengguna yang berpotensi berisi bagian yang cacat / jahat seperti ..(misalnya ../../../../../../etc/passwd). Menetapkan rootjalur mencegah jalur berbahaya seperti itu digunakan untuk mengakses file di luar jalur dasar itu.


1
apa cara terbaik untuk menentukan root sebagai direktori?
SuperUberDuper

1
@SuperUberDuper Maksud Anda seperti path.resolve(__dirname, '.../public')? Itu akan menyelesaikan ke subdirektori 'publik' dari direktori induk skrip.
mscdex

keren! apakah ini secara permanen menyimpan nilai ini di __dirname di masa mendatang?
SuperUberDuper

1
Hai, saya mencoba res.sendFile berikut (path.resolve (__ dirname + '/index.html', '../')) tetapi mendapatkan pesan: Tidak Dapat DAPATKAN
SuperUberDuper

2
@SuperUberDuper <- orang ini melakukannya dengan benar (setidaknya untuk saya). Dia menggunakan fungsi tekad yang menormalkan jalur yang memungkinkan Anda menavigasi dengan ../../<etc>sintaks tipe. Perhatikan koma antara __dirnamedan ../public. Menggunakan tanda + tidak berfungsi.
Helzgate

20

Coba tambahkan path root.

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

12

dalam file .mjs untuk saat ini kami tidak memiliki __dirname

karenanya

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

Ini adalah solusi yang bagus untuk saya karena persyaratan saya adalah kembali setelah mendapatkan path melalui __dirname. Jadi saya memberi res.sendFile ('index.html', {root: './public/views'});
nilakantha singh deo

untuk SITEMAP.XML di handelbars, ini adalah solusi yang tepat. Terima kasih banyak
titoih

3

Jika Anda mempercayai path, path.resolve adalah opsi:

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

Kesalahannya cukup mudah. Kemungkinan besar alasannya adalah bahwa file index.html Anda tidak ada di direktori root.

Atau jika ada di direktori root maka referensi relatif tidak berfungsi.

Jadi, Anda perlu memberi tahu lokasi persis lokasi file Anda. Ini bisa dilakukan dengan menggunakan metode dirname di NodeJs. Cukup ganti kode Anda dengan yang ini:

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

Pastikan bahwa Anda menambahkan simbol garis miring "/" sebelum beranda Anda. Jika tidak, jalur Anda akan menjadi: rootDirectoryindex.html

Sedangkan yang Anda inginkan adalah: rootDirectory / index.html


1

Saya mengatasi ini dengan menggunakan variabel path. Kode sampel akan terlihat seperti di bawah ini.

var path = require("path");

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

0

Jika Anda bekerja pada direktori root, maka Anda dapat menggunakan pendekatan ini

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

tetapi jika Anda menggunakan Rute yang ada di dalam folder katakanlah /Routes/someRoute.jsmaka Anda perlu melakukan sesuatu seperti ini

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

0

Dalam naskah dengan jalur relatif ke ikon:

import path from 'path';

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

0

Ini akan dialihkan ke index.html di localhost: 8080 panggilan.

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

0

Saya menggunakan kode di bawah ini dan mencoba menampilkan file sitemap.xml

router.get('/sitemap.xml', function (req, res) {
    res.sendFile('sitemap.xml', { root: '.' });
});

-1

Ini dapat diatasi dengan cara lain:

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

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

});

process.env.PWD akan menambahkan direktori kerja saat proses dimulai.


-2

Saya melakukan ini dan sekarang aplikasi saya berfungsi dengan baik,

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

Praktik buruk untuk meng-hardcode lokasi file. Jika Anda menyebarkan aplikasi ke mesin lain, jalur file kemungkinan besar akan berbeda
Merve Sahin

-3

Anda mungkin mempertimbangkan untuk menggunakan garis miring ganda pada direktori Anda, mis

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.