Есть ли способ перенаправить файл HTML из приложения Node.JS с чем-то вроде: res.sendFile
выражения и передавать данные JSON вместе с html файлом?
Res.sendfile в Node Экспресс с передачей данных вдоль
Ответ 1
Вы получаете один ответ от данного запроса. Вы можете объединить несколько вещей в один ответ или потребовать от клиента сделать отдельные запросы для получения отдельных вещей.
Если то, что вы пытаетесь сделать, - это взять файл HTML и изменить его, вставив в него некоторый JSON, тогда вы не можете использовать только res.sendFile()
, потому что это просто читает файл с диска или кеша и напрямую передает потоки это как ответ, не предлагая изменить его.
Более распространенный способ сделать это - использовать систему шаблонов, которая позволяет вставлять вещи в HTML файл (обычно заменяя специальные теги вашими собственными данными). Существует буквально сотни шаблонных систем и многие из них поддерживают node.js. Общий выбор для node.js - это Jade, Handlebars, Ember, Dust, EJS, Mustache.
Или, если вы действительно этого хотели, вы можете прочитать файл HTML в памяти, использовать для него какую-то операцию .replace()
, чтобы вставить ваши собственные данные, а затем res.send()
полученный измененный файл.
Ответ 2
Я знаю, что это поздно, но я хотел предложить решение, которое никто другой не предоставил. Это решение позволяет передавать поток в ответ, сохраняя при этом возможность изменять содержимое без необходимости использования механизма шаблонов или буферизации всего файла в памяти.
Продвигайтесь вниз, если вас не волнует "почему"
Позвольте мне сначала описать, почему res.sendFile
так желательно для тех, кто этого не знает. Поскольку Node является однопоточным, он работает, выполняя множество и очень маленьких задач подряд - это включает чтение из файловой системы и ответ на HTTP-запрос. Ни в какое время Node не останавливается на том, что он делает, и читает целое из файловой системы. Он будет читать немного, делать что-то еще, читать немного больше, делать что-то еще. То же самое касается ответа на HTTP-запрос и большинство других операций в Node (если вы явно не используете версию операции sync
, например readFileSync, не делайте этого, если вы можете помочь ей, серьезно, т - это эгоистично).
Рассмотрим сценарий, в котором 10 пользователей делают запрос для одного и того же файла. Неэффективной задачей было бы загрузить весь файл в память, а затем отправить файл с помощью res.send()
. Несмотря на то, что это тот же файл, файл будет загружен в память 10 раз отдельно перед отправкой в браузер. Затем сборщик мусора должен будет очистить этот беспорядок после каждого запроса. Код был бы невинно написан следующим образом:
app.use('/index.html', (req, res) => {
fs.readFile('../public/index.html', data => {
res.send(data);
});
});
Это кажется правильным, и это работает, но это ужасно неэффективно. Поскольку мы знаем, что Node делает вещи в небольших кусках, лучше всего будет отправить небольшие куски данных в браузер, поскольку они считываются из файловой системы. Куски никогда не хранятся в памяти, и ваш сервер теперь может обрабатывать на порядок больше трафика. Эта концепция называется потоковой передачей, и это то, что делает res.sendFile
- она передает файл непосредственно пользователю из файловой системы и освобождает память для более важных вещей. Вот как это выглядит, если вы должны сделать это вручную:
app.use('/index.html', (req, res) => {
fs.createReadStream('../public/index.html')
.pipe(res);
});
Решение
Если вы хотите продолжить передачу файла пользователю, внося небольшие изменения в него, то это решение для вас. Обратите внимание, что это не замена механизма шаблонов, а скорее используется для внесения небольших изменений в файл по мере его потоковой передачи. В приведенном ниже коде будет добавлен небольшой тег script с данными в тело HTML-страницы. Он также показывает, как добавлять или добавлять контент в поток ответов HTTP:
const Transform = require('stream').Transform;
const parser = new Transform();
parser._transform = function(data, encoding, done) {
const str = data.toString().replace('</body>', '<script>var data = {"foo": "bar"};</script></body>');
this.push(str);
done();
};
// app creation code removed for brevity
app.use('/index.html', (req, res) => {
res.write('<!-- Begin stream -->\n');
fs
.createReadStream('../public/index.html')
.pipe(parser)
.on('end', () => {
res.write('\n<!-- End stream -->')
}).pipe(res);
});
Ответ 3
У вас есть только один ответ, который вы можете вернуть с сервера. Наиболее распространенная задача - создать шаблон своего файла на сервере с nunjucks или jade. Другим вариантом является рендеринг файла на клиенте, а затем использование javascript для вызова ajax на сервер для получения дополнительных данных. Я полагаю, вы также можете установить некоторые данные в файл cookie, а затем прочитать это на стороне клиента через javascript.
Ответ 4
Хорошо, это было немного старым, но я не видел достаточного ответа, кроме "почему бы и нет". У вас есть способ передать параметры IN static file. И это довольно легко. Рассмотрите следующий код по вашему происхождению (с помощью экспресс):
let data = fs.readFileSync('yourPage.html');
if(data)
res.send(data.replace('param1Place','uniqueData'));
//else - 404
Теперь, например, просто установите cookie в файле yourPage.html, например:
<script>
var date = new Date();
document.cookie = "yourCookieName='param1Place';" +
date.setTime(date.getTime() + 3600) + ";path=/";
</script>
И вы можете явно вытащить содержимое уникальных данных из вашегоCookieName, где бы вы ни хотели, в js
Ответ 5
(Если вы не хотите, чтобы шаблон html файла вставлял json-данные в тег script). Вам нужно будет выставить конечную точку api, чтобы выразить отправку по данным на страницу, и иметь функцию на странице для доступа к ней. например,
// send the html
app.get('/', (req, res) => res.sendFile('index'));
// send json data
app.get('/data', (req, res) => res.json(data));
Теперь на стороне клиента вы можете создать запрос для доступа к этой конечной точке
function get() {
return new Promise((resolve, reject) => {
var req = new XMLHttpRequest();
req.open('GET', '/data');
req.onload = () => resolve(req.response);
});
// then to get the data, call the function
get().then((data) => {
var parsed = JSON.parse(data);
// do something with the data
});
EDIT:
Таким образом, функции стрелок, вероятно, пока не работают на стороне клиента. обязательно замените их функцией() {} в вашем реальном коде