res. sendfile в Node Express с передачей данных вдоль
Существует ли какой-либо способ перенаправления на HTML-файл с узла.JS приложение с чем-то вроде: res.sendFile экспресс и передать данные JSON вместе с html-файлом?
5 ответов:
Вы получаете один ответ от данного запроса. Вы можете либо объединить несколько вещей в один ответ, либо потребовать от клиента сделать отдельные запросы, чтобы получить отдельные вещи.
Если вы пытаетесь взять HTML-файл и изменить его, вставив в него JSON, то вы не можете использовать только
res.sendFile(), потому что это просто считывает файл с диска или кэша и непосредственно передает его в качестве ответа, не предлагая никакой возможности изменить его.Наиболее распространенный способ сделать это: чтобы использовать систему шаблонов, которая позволяет вставлять вещи в HTML-файл (обычно заменяя специальные теги своими собственными данными). Существуют буквально сотни шаблонных систем и многие из них поддерживают node.JS. Общий выбор для узла.js-это нефрит, руль, уголь, пыль, EJS, усы.
Или, если вы действительно хотите сделать это, вы можете прочитать HTML-файл в память, использовать какую-то операцию
.replace(), чтобы вставить свои собственные данные, а затемres.send()полученный измененный файл.
Я знаю, что это поздно, но я хотел предложить решение, которое никто другой не предоставил. Это решение позволяет передавать файл в ответ, но при этом позволяет изменять его содержимое без использования механизма шаблонов или буферизации всего файла в памяти.
Переходите ко дну, если вас не волнует "Почему"
Позвольте мне сначала объяснить, почемуres.sendFileтак желателен для тех, кто не знает. Поскольку узел является однопоточным, он работает, выполняя много и множество очень маленьких задач подряд - это включает в себя чтение из файловой системы и ответ на запрос http. Ни в какой момент времени Node просто прекращает то, что он делает, и читает всю файловую систему. Он будет читать немного, делать что-то еще, читать еще немного, делать что-то еще. То же самое касается ответа на http - запрос и большинства других операций в узле (если вы явно не используете версиюsyncоперации - такую как readFileSync-не делайте этого, если вы можете помочь ему, серьезно, не надо - это эгоистично).Рассмотрим сценарий, в котором 10 пользователей делают запрос на один и тот же файл. Неэффективно было бы загрузить весь файл в память, а затем отправить файл с помощью
res.send(). Несмотря на то, что это один и тот же файл, он будет загружен в память 10 раз, прежде чем будет отправлен в браузер. Затем сборщику мусора нужно будет убирать этот беспорядок после каждого запроса. Код был бы невинно написан, как это:Это кажется правильным, и это работает, но это ужасно неэффективно. Поскольку мы знаем, что Node выполняет операции небольшими порциями, лучше всего было бы отправлять небольшие порции данных в браузер по мере их считывания из файловой системы. Куски никогда не хранятся в памяти, и ваш сервер теперь может обрабатывать на порядки больше трафика. Эта концепция называется потоковой передачей, и это то, что делаетapp.use('/index.html', (req, res) => { fs.readFile('../public/index.html', data => { res.send(data); }); });res.sendFile- он передает файл непосредственно пользователю из файловой системы и сохраняет память свободна для более важных вещей. Вот как это выглядит, если вы должны были сделать это вручную:app.use('/index.html', (req, res) => { fs.createReadStream('../public/index.html') .pipe(res); });Решение
Если вы хотите продолжить потоковую передачу файла пользователю, внося в него небольшие изменения, то это решение для вас. Обратите внимание, что это не замена шаблонного движка, а скорее должно использоваться для внесения небольших изменений в файл по мере его потоковой передачи. Приведенный ниже код добавит небольшой тег скрипта с данными в тело 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); });
У вас есть только один ответ, который вы можете вернуть с сервера. Наиболее распространенной вещью было бы создать шаблон вашего файла на сервере с помощью nunjucks или jade. Другой вариант-визуализировать файл на клиенте, а затем использовать javascript для выполнения ajax-вызова сервера для получения дополнительных данных. Я полагаю, что вы также можете установить некоторые данные в куки, а затем прочитать их на стороне клиента через javascript.
Ну, это немного старо, но я не видел никакого достаточного ответа, кроме "почему бы и нет". У вас есть способ передать параметры в статическом файле. И это очень просто. Рассмотрим следующий код на вашем оригинале (с помощью express):
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>И вы можете просто вытащить содержимое uniqueData из yourCookieName в любом месте вашего js
(Если только вы не хотите создать шаблон html-файла для вставки данных json в тег скрипта). Вам нужно будет предоставить конечную точку api в express для отправки данных на страницу и иметь функцию на странице для доступа к ней. например,
// 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 });Правка:
Таким образом, функции arrow, вероятно, еще не работают на стороне клиента. обязательно замените их функцией () {} в вашем реальном коде
Comments