最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to import data from CSV file into Meteor collection at server side - Stack Overflow

programmeradmin4浏览0评论

I'm trying to find a solution for my previous post: Mongo gives duplicate key error on _id_ field in Meteor application

In order to do that I want to read data from my CSV file at server side, and not from the client.

First I tried the solution in this post Using node-csv and meteor-file to import CSV into a collection but meteor-file isn't patible anymore with current version of Meteor. I also tried the solution in this post Upload Data to Meteor / Mongo DB but It's also on the client and that solution generates the same error as in my previous post.

After some further research I tried to read the data with the code below. However it doesn't work:

First I created a collection:

 Meteor.orders = new Meteor.Collection('Orders');

I defined the following template to read the csv file:

<template name="read_file_orders">
  <form class="well form-inline">
   <label class="control-label" for="fileInput2">Kies bestand</label>
   <input class="input-file" id="fileInput2" type="file" name="files[]">
   <Button class="btn btn-primary" id="read_orders">Importeer</button>
   <button class="btn btn-danger" id="erase_orders">Wis gegevens</button>
  </form>
</template>

This is the client javascript:

Template.read_file_orders.events({
 "click #read_orders" : function(e) {
  var f = document.getElementById('fileInput2').files[0];
  console.log("read file");
   readFile(f, function(content) {
    Meteor.call('upload',content);
   });
 }
});

readFile = function(f,onLoadCallback) {
 var reader = new FileReader();
 reader.onload = function (e){
  var contents=e.target.result
  onLoadCallback(contents);
 }
 reader.readAsText(f);
};

And this is the server javascript:

Meteor.startup(function () {
// code to run on server at startup

 return Meteor.methods({
  upload : function(fileContent) {
    console.log("start insert");
    import_file_orders(fileContent);
    console.log("pleted");
  }
 });

});

import_file_orders = function(file) {
var lines = file.split('%\r\n');
var l = lines.length - 1;
for (var i=0; i < l; i++) {
  var line = lines[i];
  var line_parts = line.split('|');
  var ex_key = line_parts[0];
  var ex_name = line_parts[1];
  var clin_info = line_parts[2];
  var order_info = line_parts[3];
  var clinician_last_name = line_parts[4];
  var clinician_first_name = line_parts[5];
  var clinician_code = line_parts[6];
  var clinician_riziv = line_parts[7]
  var pat_id = line_parts[8];
  Meteor.orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician_first:clinician_first_name, Clinician_last:clinician_last_name, Clinician_c_code:clinician_code, Clinician_riziv:clinician_riziv, Planned:null});
  console.log("%");
};

When I try reading the file, nothing happens. Only the console logs appear in the server console but there is nothing imported. Even the Orders collection isn't created.

It's clear that I'm doing something wrong but I don't know what exactly. However I think the solution isn't too far. Maybe someone of you can show me the right direction?

Kind regards

EDIT:

In order to revmen's answer here's the full code of my testapp:

test.html:

<head>
 <title>test</title>
</head>

<body>
 <h1>Wele to Meteor!</h1>
 {{> read_file_orders}}
</body>

<template name="read_file_orders">
 <form class="well form-inline">
  <label class="control-label" for="fileInput2">Kies bestand</label>
  <input class="input-file" id="fileInput2" type="file" name="files[]">
  <Button class="btn btn-primary" id="read_orders">Importeer</button>
  <button class="btn btn-danger" id="erase_orders">Wis gegevens</button>
 </form>
</template>

test.js

Orders = new Mongo.Collection("orders");

if (Meteor.isClient) {
// counter starts at 0

Template.read_file_orders.events({
 "click #read_orders" : function(e) {
  var f = document.getElementById('fileInput2').files[0];
  console.log("read file");
  readFile(f, function(content) {
    Meteor.call('upload',content);
  });
 }
});

import_file_orders = function(file) {
 console.log("enter function import_file_orders")
 var lines = file.split(/\r\n|\n/);
 var l = lines.length - 1;
 for (var i=0; i < l; i++) {
  var line = lines[i];
  var line_parts = line.split(',');
  var ex_key = line_parts[0];
  var ex_name = line_parts[1];
  var clin_info = line_parts[2];
  var order_info = line_parts[3];
  var clinician_last_name = line_parts[4];
  var clinician_first_name = line_parts[5];
  var clinician_code = line_parts[6];
  var clinician_riziv = line_parts[7]
  var pat_id = line_parts[8];
  var result = Orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician:{first:clinician_first_name, last:clinician_last_name, c_code:clinician_code, riziv:clinician_riziv}, Planned:null});
  console.log(Orders.findOne(result));
 };
}

readFile = function(f,onLoadCallback) {
//When the file is loaded the callback is called with the contents as a string
var reader = new FileReader();
reader.onload = function (e){
  var contents=e.target.result
  onLoadCallback(contents);
}
reader.readAsText(f);
};

}

if (Meteor.isServer) {
  Meteor.startup(function () {
  // code to run on server at startup

 });

 Meteor.methods({
   upload : function(fileContent) {
   console.log("start insert");
   import_file_orders(fileContent);
   console.log("pleted");
 }
});

}

I'm trying to find a solution for my previous post: Mongo gives duplicate key error on _id_ field in Meteor application

In order to do that I want to read data from my CSV file at server side, and not from the client.

First I tried the solution in this post Using node-csv and meteor-file to import CSV into a collection but meteor-file isn't patible anymore with current version of Meteor. I also tried the solution in this post Upload Data to Meteor / Mongo DB but It's also on the client and that solution generates the same error as in my previous post.

After some further research I tried to read the data with the code below. However it doesn't work:

First I created a collection:

 Meteor.orders = new Meteor.Collection('Orders');

I defined the following template to read the csv file:

<template name="read_file_orders">
  <form class="well form-inline">
   <label class="control-label" for="fileInput2">Kies bestand</label>
   <input class="input-file" id="fileInput2" type="file" name="files[]">
   <Button class="btn btn-primary" id="read_orders">Importeer</button>
   <button class="btn btn-danger" id="erase_orders">Wis gegevens</button>
  </form>
</template>

This is the client javascript:

Template.read_file_orders.events({
 "click #read_orders" : function(e) {
  var f = document.getElementById('fileInput2').files[0];
  console.log("read file");
   readFile(f, function(content) {
    Meteor.call('upload',content);
   });
 }
});

readFile = function(f,onLoadCallback) {
 var reader = new FileReader();
 reader.onload = function (e){
  var contents=e.target.result
  onLoadCallback(contents);
 }
 reader.readAsText(f);
};

And this is the server javascript:

Meteor.startup(function () {
// code to run on server at startup

 return Meteor.methods({
  upload : function(fileContent) {
    console.log("start insert");
    import_file_orders(fileContent);
    console.log("pleted");
  }
 });

});

import_file_orders = function(file) {
var lines = file.split('%\r\n');
var l = lines.length - 1;
for (var i=0; i < l; i++) {
  var line = lines[i];
  var line_parts = line.split('|');
  var ex_key = line_parts[0];
  var ex_name = line_parts[1];
  var clin_info = line_parts[2];
  var order_info = line_parts[3];
  var clinician_last_name = line_parts[4];
  var clinician_first_name = line_parts[5];
  var clinician_code = line_parts[6];
  var clinician_riziv = line_parts[7]
  var pat_id = line_parts[8];
  Meteor.orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician_first:clinician_first_name, Clinician_last:clinician_last_name, Clinician_c_code:clinician_code, Clinician_riziv:clinician_riziv, Planned:null});
  console.log("%");
};

When I try reading the file, nothing happens. Only the console logs appear in the server console but there is nothing imported. Even the Orders collection isn't created.

It's clear that I'm doing something wrong but I don't know what exactly. However I think the solution isn't too far. Maybe someone of you can show me the right direction?

Kind regards

EDIT:

In order to revmen's answer here's the full code of my testapp:

test.html:

<head>
 <title>test</title>
</head>

<body>
 <h1>Wele to Meteor!</h1>
 {{> read_file_orders}}
</body>

<template name="read_file_orders">
 <form class="well form-inline">
  <label class="control-label" for="fileInput2">Kies bestand</label>
  <input class="input-file" id="fileInput2" type="file" name="files[]">
  <Button class="btn btn-primary" id="read_orders">Importeer</button>
  <button class="btn btn-danger" id="erase_orders">Wis gegevens</button>
 </form>
</template>

test.js

Orders = new Mongo.Collection("orders");

if (Meteor.isClient) {
// counter starts at 0

Template.read_file_orders.events({
 "click #read_orders" : function(e) {
  var f = document.getElementById('fileInput2').files[0];
  console.log("read file");
  readFile(f, function(content) {
    Meteor.call('upload',content);
  });
 }
});

import_file_orders = function(file) {
 console.log("enter function import_file_orders")
 var lines = file.split(/\r\n|\n/);
 var l = lines.length - 1;
 for (var i=0; i < l; i++) {
  var line = lines[i];
  var line_parts = line.split(',');
  var ex_key = line_parts[0];
  var ex_name = line_parts[1];
  var clin_info = line_parts[2];
  var order_info = line_parts[3];
  var clinician_last_name = line_parts[4];
  var clinician_first_name = line_parts[5];
  var clinician_code = line_parts[6];
  var clinician_riziv = line_parts[7]
  var pat_id = line_parts[8];
  var result = Orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician:{first:clinician_first_name, last:clinician_last_name, c_code:clinician_code, riziv:clinician_riziv}, Planned:null});
  console.log(Orders.findOne(result));
 };
}

readFile = function(f,onLoadCallback) {
//When the file is loaded the callback is called with the contents as a string
var reader = new FileReader();
reader.onload = function (e){
  var contents=e.target.result
  onLoadCallback(contents);
}
reader.readAsText(f);
};

}

if (Meteor.isServer) {
  Meteor.startup(function () {
  // code to run on server at startup

 });

 Meteor.methods({
   upload : function(fileContent) {
   console.log("start insert");
   import_file_orders(fileContent);
   console.log("pleted");
 }
});

}
Share Improve this question edited May 23, 2017 at 10:34 CommunityBot 11 silver badge asked Mar 12, 2015 at 16:28 QuantumQuantum 1434 silver badges10 bronze badges 1
  • I am using the same code but unfortunately, I am receiving a non-human-readable text at the reader.readAsText(f); Is there any way to parse it? – Anand Vaidya Commented Apr 18, 2018 at 10:30
Add a ment  | 

1 Answer 1

Reset to default 6

You were very close. I just had to make a few changes to get it working.

I don't know what your .csv file looks like, so I made one that's like this:

A1, B1, C1, D1, E1, F1, G1, H1, I1
A2, B2, C2, D2, E2, F2, G2, H2, I2

Your file.split operation wasn't splitting the lines, but was putting everything on one big line. I did it this way and it worked:

var lines = file.split(/\r\n|\n/);

That got individual lines to split into members of the array. Then I assumed that, since you're calling your input a CSV, your values are separated by mas, not pipes. So I changed your line.split to this

var line_parts = line.split(',');

Other changes I made may not be what was causing yours to fail, but this is how I think things are normally done...

Instead of declaring your collection like this

Meteor.orders = new Meteor.Collection('Orders');

I did it like this

Orders = new Mongo.Collection("orders");

Note that this is run by both the server and the client.

Instead of your way of declaring methods on the server, I just put this into server code (not in Meteor.start):

Meteor.methods({
    upload : function(fileContent) {
        console.log("start insert");
        import_file_orders(fileContent);
        console.log("pleted");
    }
});

And, of course, I changed the insert line at the bottom of your import_file_orders function

var result = Orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician_first:clinician_first_name, Clinician_last:clinician_last_name, Clinician_c_code:clinician_code, Clinician_riziv:clinician_riziv, Planned:null});
console.log(Orders.findOne(result));

EDIT for updated code in the question:

Move the import_file_orders function from the client block to the server block.

发布评论

评论列表(0)

  1. 暂无评论