0

I have a Meteor app where I'd like to upload a text file then have the file parsed on the server. I'm using cfs:gridfs (with cfs:standard-package, of course) to store the files on the server.

Client code:

Template.uploadPathway.events({
  "submit #upload-pathway": function (event) {
    event.preventDefault(); // prevent default browser form submit

    var pathwayFile = event.target.pathwayFile.files[0];

    UploadedFiles.insert(pathwayFile, function(error, fileObject) {
      // error handling removed for brevity
      Meteor.call("parseFile", fileObject._id);
    });
  }
});

Server code (in server folder, not Meteor.isServer):

Meteor.methods({
  parseFile: function (fileId) {
    var theFile = UploadedFiles.findOne({ _id: fileId });
    console.log(theFile);
    // how do I parse this file??
  }
});

The above code works beautifully, but I have no idea how to read the data inside the FS.File

Mokolodi1
  • 119
  • 1
  • 10
  • 1
    you can use `theFile.createReadStream()` to read the file. Once you have that, you can search stack overflow for ideas on how to read a text file line by line given a stream, e.g., http://stackoverflow.com/questions/6156501/read-a-file-one-line-at-a-time-in-node-js. – Christian Fritz Jul 21 '15 at 19:56
  • @ChristianFritz: The problem was that `theFile.createReadStream()` would crash because the file hadn't finished saving yet. (See answer below.) – Mokolodi1 Jul 24 '15 at 20:17

1 Answers1

0

Eric Dobbertin's answer to my question:

First, note that when the insert callback fires on the client, the file is probably not done uploading yet, and even if it’s been uploaded, might not be done storing to the data store. So calling your method in the insert callback isn’t a good way to do this.

If you need to do it in a method, because you want to read the data and send something back to the client, then you could set up an autorun function where you wait for fileObj.hasStored(storeName) to be true. Then you can call the method and stop the autorun computation. (link to hasStored documentation)

Try something like that and then see if your code works. Depending on what exactly you are trying to do with the data, there may be some better way to do it instead of the “data” event handler.

If the client does not need to be involved, then a simpler way to trigger your code after each file is stored is to use a "stored" listener on the store:

UploadedFileStore.on("stored", function (storeName, fileObject) {
  if (storeName !== UploadedFileStore.name) return; // workaround for known bug

  // your code

  fileObject.createReadStream("uploaded_files")
    .on('data', function (chunk) {
      console.log("chunk: " + chunk);
    });
});
Mokolodi1
  • 119
  • 1
  • 10