Hey guys,
I am trying to implement a “batch import” feature on my app that allows users to import data through a .csv file that automatically adds them to a Mongo Collection. I am using the clinical:csv
package.
However, I can’t figure out how to get the part that comes before the Mongo insertion done…
How do I create an “import your file here” button that opens the user’s file explorer and gets the file?
How do I check if the uploaded file is truly .csv and in the right format?
Any ideas? Thanks!
raragao
February 7, 2019, 11:42pm
2
https://www.papaparse.com is the best library to handle CSV.
Others links:
Really grateful for the feedback! @a.com , I had seen your posts earlier wrestling with CSVs and learned a lot.
@efrancis : Thanks for pointing me in the right direction! Here’s the code I ended up using that streams data from S3 to a local file, then processes the local file. I’m sure there’s a way to simplify and just process the remote file from S3, but I need to move on.
This is called from a client-side event that parses just the first 3 rows of the file so users get a preview and can map t…
gj on digging up 1 year old thread. anyway since people might come across this from search engines, here is what i did:
Template.importList.events({
'click #upload': function(event, template){
event.preventDefault();
var listId = Router.current().params._id;
var imported = template.find('#uploadCSV').files[0];
Papa.parse(imported, {
header: true,
complete(results, file){
Meteor.call('parseUpload', results.data, listId, (error, response) => {
if(…
Papaparse is very good. We used it as a base in our clinical:csv package, and extended it with a) isomorphic import/exports on b) both server & client and c) documentation and code samples.
1 Like
Hi @patrickcneuhaus ,
I use papaparse to parse the csv into json, Ill post a code example of how I do it using react. I havent tested this I just extracted parts of my code for this example.
To validate the data I do it on the method using simpleschema, bubt you can also do it with simple schema on the _importUsersBatch function.
class MyView extends Component {
_importUsersBatch = async (event) => {
event.preventDefault();
this.setState({ errors: [], loading: true });
const file = event.target.files[0];
const results = await parseCSV(file);
results.data.splice(0, 1);
let contacts = results.data;
// TODO: Validate before upload
contacts = contacts.filter((contact) => !!contact[0]).map((contact) => {
return {
unitCode: contact[0].toString(),
firstName: contact[1] || undefined,
lastName: contact[2] || undefined,
email: contact[3] || undefined,
phone: contact[4] ? contact[4].toString() : undefined,
gender: contact[5] || undefined,
birthdate: contact[6] || undefined,
contactType: contact[7] || undefined
};
});
const params = {
objects: contacts
};
try {
await asyncCall('importBatch', params);
} catch (error) {
this.setState({ error });
} finally {
this.setState({ loading: false });
}
};
return (
<div>
<label htmlFor="input">
<Button
as="div"
icon
color={ this.state[file.id] ? 'green' : undefined }
className="fluid-mobile">
<Icon name={ this.state[file.id] ? 'checkmark' : 'upload' }/>
</Button>
</label>
<input
id="input"
name="input"
type="file"
accept=".csv"
disabled={ loading }
className="hidden"
onChange={ this._importUsersBatch }/>
</div>
);
}
function parseCSV(file) {
return new Promise(function(resolve, reject) {
parse(file, {
dynamicTyping: true,
skipEmptyLines: true,
error(error) {
Sentry.captureException(error);
reject(error);
},
complete(results) {
resolve(results);
}
});
});
}
```
Hope this helps
1 Like