เส้นทางสัมบูรณ์ res.sendFile


139

ถ้าฉันทำ

res.sendfile('public/index1.html'); 

จากนั้นฉันได้รับคำเตือนคอนโซลเซิร์ฟเวอร์

เลิกใช้ด่วนres.sendfile: ใช้res.sendFileแทน

แต่ทำงานได้ดีในฝั่งไคลเอ็นต์

แต่พอเปลี่ยนเป็น

res.sendFile('public/index1.html');

ฉันได้รับข้อผิดพลาด

TypeError: พา ธ ต้องเป็นค่าสัมบูรณ์หรือระบุรูทเป็น res.sendFile

และindex1.htmlไม่แสดงผล

ฉันนึกไม่ออกว่าเส้นทางที่แน่นอนคืออะไร ฉันมีpublicไดเร็กทอรีในระดับเดียวกับserver.js. ฉันกำลังทำres.sendFileจากserver.js. ฉันยังได้ประกาศapp.use(express.static(path.join(__dirname, 'public')));

การเพิ่มโครงสร้างไดเร็กทอรีของฉัน:

/Users/sj/test/
....app/
........models/
....public/
........index1.html

อะไรคือเส้นทางที่แน่นอนที่จะระบุที่นี่?

ฉันใช้ Express 4.x.


หากคุณใช้express.staticมิดเดิลแวร์เพื่อให้บริการไดเรกทอรีสาธารณะของคุณทำไมคุณต้องres.sendFileส่งpublic/index1.html?
Mike S

1
ฉันโทรres.sendFileจากภายในapp.get('/', function(req, res){res.sendFile("...")})เพื่อส่งตามคำขอ
Kaya Toast

คำตอบ:


315

express.staticมิดเดิลแวร์จะแยกจากres.sendFileดังนั้นการเริ่มต้นด้วยเส้นทางที่แน่นอนที่คุณไดเรกทอรีจะไม่ทำอะไรเพื่อpublic คุณจำเป็นต้องใช้เส้นทางที่แน่นอนโดยตรงกับres.sendFile res.sendFileมีสองวิธีง่ายๆในการทำ:

  1. res.sendFile(path.join(__dirname, '../public', 'index1.html'));
  2. res.sendFile('index1.html', { root: path.join(__dirname, '../public') });

หมายเหตุ: การ __dirnameส่งกลับไดเรกทอรีที่สคริปต์ในขณะนี้การดำเนินการอยู่ในในกรณีของคุณดูเหมือนว่า. อยู่ในserver.js app/ดังนั้นเพื่อให้ได้คุณจะต้องกลับออกมาหนึ่งระดับแรก:public../public/index1.html

หมายเหตุ: pathเป็นโมดูลในตัวที่ต้องเป็นrequired เพื่อให้โค้ดด้านบนทำงานได้:var path = require('path');


16
res.sendFile('../public/index.html', {root: __dirname});ยังใช้งานได้และสั้นกว่า
Fabien Sa

การทำงานกับ express และ webstorm ide: ไม่มีข้อผิดพลาดconsole.log(path.join(__dirname, '../public', 'index.html'));แต่res.sendFile(path.join(__dirname, '../public', 'index.html'));ใช้ได้เฉพาะกับ var path = require('path');
Quake1TF

ไม่มีวิธีกำหนดเส้นทางสัมบูรณ์ล่วงหน้าเพื่อให้สามารถใช้ใน sendFile ได้หรือไม่?
eran otzap

4
res.sendFile('../public/index.html', {root: __dirname});ไม่ทำงาน (อีกต่อไป) เนื่องจากส่งคืน 403 Forbidden เนื่องจากอยู่เหนือรูท ทำres.sendFile('public/index.html', {root: path.dirname(__dirname)});แทน
Trevor Robinson

51

ลองสิ่งนี้แทน:

res.sendFile('public/index1.html' , { root : __dirname});

สิ่งนี้ได้ผลสำหรับฉัน รูท: __ dirname จะรับที่อยู่โดยที่ server.js อยู่ในตัวอย่างด้านบนจากนั้นไปที่ index1.html (ในกรณีนี้) เส้นทางที่ส่งคืนคือไปยังไดเร็กทอรีที่โฟลเดอร์สาธารณะอยู่


เหตุใดจึงไม่มีเอกสารตัวเลือกนี้
timkay

9
res.sendFile( __dirname + "/public/" + "index1.html" );

โดยที่__dirnameจะจัดการชื่อของไดเร็กทอรีที่มีสคริปต์ที่เรียกใช้งานserver.jsอยู่( ) อยู่


การแก้ปัญหานี้ค่อนข้างตรงไปตรงมาขอบคุณสำหรับความช่วยเหลือ .. ฉันสงสัยว่าทำไมคนถึงแนะนำให้ใช้แพ็คเกจ 'เส้นทาง' เพื่อทำเช่นเดียวกัน
ที่สาม

3
@ ประการที่สามฉันเดาว่าการใช้pathทำให้มันไม่ขึ้นกับระบบปฏิบัติการ
kmonsoor

7

อีกทางเลือกหนึ่งที่ยังไม่ได้อยู่ในรายการที่ใช้งานได้สำหรับฉันคือการใช้path.resolveกับสตริงที่แยกจากกันหรือเพียงรายการเดียวกับเส้นทางทั้งหมด:

// comma separated
app.get('/', function(req, res) {
    res.sendFile( path.resolve('src', 'app', 'index.html') );
});

หรือ

// just one string with the path
app.get('/', function(req, res) {
    res.sendFile( path.resolve('src/app/index.html') );
});

(โหนด v6.10.0)

ไอเดียมาจากhttps://stackoverflow.com/a/14594282/6189078


6

จากคำตอบอื่น ๆ นี่เป็นตัวอย่างง่ายๆในการบรรลุข้อกำหนดที่พบบ่อยที่สุด:

const app = express()
app.use(express.static('public')) // relative path of client-side code
app.get('*', function(req, res) {
    res.sendFile('index.html', { root: __dirname })
})
app.listen(process.env.PORT)

นอกจากนี้ยังเพิ่มเป็นสองเท่าของวิธีง่ายๆในการตอบกลับด้วย index.html ในทุกคำขอเนื่องจากฉันใช้ดาว*เพื่อจับไฟล์ทั้งหมดที่ไม่พบในไดเร็กทอรีแบบคงที่ (สาธารณะ) ของคุณ ซึ่งเป็นกรณีการใช้งานที่พบบ่อยที่สุดสำหรับเว็บแอป เปลี่ยนเป็น/เพื่อส่งคืนดัชนีในพา ธ รากเท่านั้น


ดี. ดีและรวบรัด
lharby

5

ฉันลองสิ่งนี้และได้ผล

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

4

process.cwd() ส่งคืนเส้นทางสัมบูรณ์ของโครงการของคุณ

จากนั้น:

res.sendFile( `${process.cwd()}/public/index1.html` );

3

อีกวิธีหนึ่งที่ทำได้โดยการเขียนโค้ดน้อยลง

app.use(express.static('public'));

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

5
สิ่งนี้สร้าง "TypeError: path ต้องเป็นค่าสัมบูรณ์หรือระบุ root เป็น res.sendFile"
GreenAsJade

1

คุณสามารถใช้ send แทน sendFile ดังนั้นคุณจะไม่ต้องเผชิญกับข้อผิดพลาด! งานนี้จะช่วยคุณได้!

fs.readFile('public/index1.html',(err,data)=>{
if(err){
  consol.log(err);
}else {
res.setHeader('Content-Type', 'application/pdf');

เพื่อบอกเบราว์เซอร์ว่าการตอบกลับของคุณเป็นประเภท PDF

res.setHeader('Content-Disposition', 'attachment; filename='your_file_name_for_client.pdf');

หากคุณต้องการให้ไฟล์นั้นเปิดขึ้นทันทีในหน้าเดียวกันหลังจากที่ผู้ใช้ดาวน์โหลดแล้วให้เขียน 'inline' แทนไฟล์แนบในโค้ดด้านบน

res.send(data)

0

หากคุณต้องการตั้งค่านี้เพียงครั้งเดียวและใช้งานได้ทุกที่เพียงกำหนดค่ามิดเดิลแวร์ของคุณเอง เมื่อคุณกำลังตั้งค่าแอปของคุณให้ใช้สิ่งต่อไปนี้เพื่อกำหนดฟังก์ชันใหม่บนวัตถุตอบสนอง:

app.use((req, res, next) => {
  res.show = (name) => {
    res.sendFile(`/public/${name}`, {root: __dirname});
  };
  next();
});

จากนั้นใช้ดังนี้:

app.get('/demo', (req, res) => {
  res.show("index1.html");
});

0

ฉันใช้ Node.Js และมีปัญหาเดียวกัน ... ฉันแก้ไขได้เพียงแค่เพิ่ม '/' ในการเรียกทุกสคริปต์และลิงก์ไปยังไฟล์คงที่ css

ก่อน:

<link rel="stylesheet" href="assets/css/bootstrap/bootstrap.min.css">

หลังจาก:

<link rel="stylesheet" href="/assets/css/bootstrap/bootstrap.min.css">

คุณจะต้องตั้งค่าเซิร์ฟเวอร์คงที่ด่วนเพื่อให้สิ่งนี้ทำงานได้
Hum4n01d
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.