使用nodejs服务器,我需要将以下所示的数据从文本文件流式传输到客户端浏览器。
文本文件中的每一行都是一个json对象,代表表中的一条记录。
{"userId":443,"email":"bob@gmail.com","hashedPassword":"36583a77a098c02ef111e2f2521d77b58e420f2bc7e9bf930ec24b21d42ea2e0","timeStamp":1567439821109,"deleted":false}
{"userId":447,"email":"alice@gmail.com","hashedPassword":"36583a77a098c02ef111e2f2521d77b58e420f2bc7e9bf930ec24b21d42ea2e0","timeStamp":1567439909013,"deleted":false}
{"userId":451,"email":"cliff@gmail.com","hashedPassword":"36583a77a098c02ef111e2f2521d77b58e420f2bc7e9bf930ec24b21d42ea2e0","timeStamp":1567443638340,"deleted":false}
...
本文结尾处显示的nodejs函数已成功将文本文件流式传输到服务器上的新文件。
所以sourceStream很好。
该函数还通过回调将sourceStream发送到浏览器。
当我在客户端浏览器中console.log(responseTextStream)
时,我得到以下缓冲区。
[123, 34, 117, 115, 101, 114, 73, 100, 34, 58, 52, 52, 51, 44, 34, 101, 109, 97, 105, 108, 34, 58, 34, 98, 111, 98, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109, 34, 44, 34, 116, 105, ...]
所以我知道数据正在到达客户端。
我的问题是:我不知道如何在客户端上使用流。
以下伪代码显示了我正在尝试使用浏览器中的javascript处理流。
有人可以让我走上正确的路吗?
谢谢,约翰
// Populate the dbUsersList webpage with user records.
app.loadUsersListPage = function()
{
// Define which users will be retrieved from dbUsers.json
// This is not being used for now so all records will be retrived.
var QueryStringObject = {};
// Ask the server for the JSON records found in the dbUsers file which match the QueryStringObject.
// Then run the callback function defined here which inserts rows into the usersListTable on the webpage
// and populates them with data from the file of JSON records returned.
app.client.request(undefined,'api/aUsers','GET',QueryStringObject,undefined,function(statusCode,responseTextStream)
{
// if the call to handlers._users.get which is mapped to api/aUsers called back success.
if(statusCode == 200)
{
console.log(responseTextStream); // I can see the buffer is populated with data.
// Create a handle which can be used to manipulate the table on the webpage.
var table = document.getElementById("usersListTable");
// This next line causes an error because I am trying to use the
// split function on a stream but it demonstrates what I am
// trying to accomplish.
// I want to split the stream on each new line so that I can work
// with the json objects representing the records one at a time.
var recordsArray = responseTextStream.split('\n');
recordsArray.forEach(function(jsonString)
{
var recordObject = JSON.parse(jsonString);
if(recordObject)
{
// Insert a new row in the table.
var tr = table.insertRow(-1);
// Make the new row a member of the class 'checkRow'
tr.classList.add('checkRow');
// Insert five new cells into the new row.
var td0 = tr.insertCell(0);
var td1 = tr.insertCell(1);
var td2 = tr.insertCell(2);
var td3 = tr.insertCell(3);
// load the new cells with data from the recordObject.
td0.innerHTML = recordObject.userId;
td1.innerHTML = recordObject.email;
td2.innerHTML = recordObject.timeStamp;
td3.innerHTML = '<a href="/users/edit?email=' + recordObject.userId + '">View / Edit / Delete</a>';
}; // End of: if(recordObject)
}); // End of: recordsArray.forEach(...)
} // End of: if the call to handlers._users.get which is mapped to api/aUsers called back successfully.
} // End of: app.loadUsersListPage = function(){...}
// End of: Populate the dbUsersList webpage with user records.
这是nodejs服务器功能,可将我的文本文件流式传输到浏览器。
这很好。这里没有问题。仅出于清楚目的而包含了它。
handlers._users.get = function(data, callback)
{
// Create an empty map data structure which will be used to merge user records with the same email address.
let usersMap = new Map();
// This function sets up a stream where each chunk of data is a complete line in the dbUsers file.
let readInterface = readline.createInterface
(
{ // specify the file to be read.
input: fs.createReadStream(_data.baseDir + '/dbPermissions/dbUsers' + '/' + 'dbUsers' + '.json'),
}
);
// Now look at each record in the file and merge them into a map.
readInterface.on('line', function(line)
{
// Convert the JSON string (a single line from the dbUsers file) into lineValueObject.
// These objects will written back to a new file after deleting some un-needed key/value pairs.
let lineValueObject = JSON.parse(line);
// Declare a variable to serve as a key in the map to manage the lineValueObject.
let userId = lineValueObject.userId;
if(lineValueObject.deleted === true)
{
// Remove this record from the map
usersMap.delete(userId);
}
else // this record has not been marked for deletion.
{
// Remove the hashed password key/value pair from the lineValueObject before returning it to the requester.
delete lineValueObject.hashedPassword;
// Remove the deleted key/value pair from the lineValueObject before returning it to the requester.
delete lineValueObject.deleted;
// Update this record in the map.
usersMap.set(userId, lineValueObject);
}
}); // End of: readInterface.on('line', function(line){...}
// End of: Look at each record...
// This listener fires after we have looked through all the records in the dbUsers file.
// The callback function defined here will stream the list of users back to the clients browser.
readInterface.on('close', function()
{
// This readable stream will be used to write the result of the merge to a new file.
const sourceStream = new Readable();
for (const [key, valueObject] of usersMap)
{
// Convert the data object to a string.
let stringData = JSON.stringify(valueObject);
// Load the readable stream with data.
sourceStream.push(stringData + '\n');
}
// Tell the stream no more data is coming.
sourceStream.push(null);
// Create a writable stream and specify the file which will receive the data from the readable stream.
let destinationStream = fs.createWriteStream(_data.baseDir + '/dbPermissions/dbUsers' + '/' + 'test' + '.txt', {flags : 'a'});
// Populate the new text file from the sourceStream.
// This is just to check that sourceStream is working as expected before sending the data to the client.
// The pipeline will be removed when my problem has been solved.
pipeline
(
sourceStream,
destinationStream,
function(error){if(error){console.log('There was an error.');}}
);
// Send the source stream to the client's browser
callback(200, sourceStream);
}); // End of: readInterface.on('close', function(){...}
}; // End of: handlers._users.get = function(data, callback){do stuff}
答案 0 :(得分:0)
尝试:
var Astr = responseTextStream;
var line = "";
for(var i=0; i<Astr.length; i++){
var chr = String.fromCharCode(Astr[i]);
if(chr == "\n" || chr == "\r"){
console.log("line: ",line);
// do something with the line here
// clear the line buffer to start the next line.
line = "";
} else {
line += chr;
}
}