Acest subiect este unul foarte plăcut pentru mine. Este destul de comună în multe aplicații web să accepte intrarea utilizatorilor și să salveze o singură înregistrare în baza dvs. de date. Dar ce se întâmplă atunci când utilizatorii (sau dvs.) vor să efectueze mai multe intrări într-o singură comandă?
Introduceți acest articol, care va demonstra cum să creați un șablon CSV și un formular pentru încărcarea fișierului CSV și cum să analizați CSV-ul într-un model Mongoose care va fi salvat într-o bază de date MongoDB.
Acest articol presupune că aveți o înțelegere de bază despre Mongoose și modul în care interacționează cu MongoDB. Dacă nu, aș sugera citirea introducerii introducerii în Mongoose pentru articolul MongoDB și Node.js. Acest articol descrie modul în care Mongoose interacționează cu MongoDB prin crearea schemelor puternic tipizate de la care este creat un model. Dacă aveți deja o bună înțelegere a Mongoose, atunci hai să continuăm.
Pentru a începe, să instanțiăm o nouă aplicație Node.js. Într-un prompt de comandă, navigați la locul unde doriți să găzduiți aplicațiile Node.js și efectuați următoarele comenzi:
mkdir csvimport cd csvimport npm init
Am lăsat toate setările implicite, așa că cererea mea va începe cu index.js
. Înainte de a crea și parsa fișiere CSV, este necesar să faceți mai întâi o instalare inițială. Vreau să fac acest lucru o aplicație web; pentru a face acest lucru, am de gând să folosesc pachetul Express pentru a rezolva toate configurațiile serverului de tip "nitty-gritty". În linia de comandă, instalați Express executând următoarea comandă:
npm install express - salvați
Deoarece această aplicație web va accepta fișiere printr-un formular web, voi folosi și sub-pachetul Express Express Upload. Să instalăm și acum:
npm install express-fileupload - salvați
Am făcut deja o configurație inițială suficientă pentru a configura aplicația mea web și pentru a crea o pagină web de bază care va crea formularul de încărcare a fișierului meu.
Aici e al meu index.js
fișier care configurează serverul meu web:
var app = necesită ('express') (); var fileUpload = necesită ('express-fileupload'); serverul var = necesită ("http"). Server (app); app.use (fileUpload ()); server.listen (80); app.get ('/', funcția (req, res) res.sendFile (__ dirname + '/ index.html'););
Acest exemplu importă Express și bibliotecile Express File Upload, configurează aplicația mea web pentru a utiliza Încărcarea fișierelor și ascultă pe portul 80. Acest exemplu a creat, de asemenea, un traseu folosind Express la "/" care va fi pagina de destinație implicită pentru web-ul meu cerere. Această rută returnează o index.html
fișier care conține formularul web care va permite unui utilizator să încarce un fișier CSV. În cazul meu, rulez pe computerul meu local, așa că atunci când vizitez http: // localhost, voi vedea forma pe care o creez în următorul exemplu.
Aici e al meu index.html
pagina care creează formularul meu pentru încărcarea unui fișier CSV:
Încărcați autori Utilizați formularul de mai jos pentru a încărca o listă de autori. Faceți clic aici pentru un exemplu de șablon.
Acest fișier HTML conține două lucruri importante:
eNCTYPE
a seta ca multipart / form-data
și un câmp de introducere cu un tip de fişier
care acceptă fișiere cu o extensie "csv".După cum ați observat, codul HTML face trimitere la un șablon de autor. Dacă ați citit articolul meu introductiv în Mongoose, am creat o schemă de autor. În acest articol, voi recrea această schemă și voi permite utilizatorului să importe în vrac o colecție de autori în baza de date MongoDB. Să aruncăm o privire la schema de autor. Înainte de a face asta, probabil că ați bănuit-o - trebuie să instalați pachetul Mongoose:
npm instala mongoose - salveaza
Cu Mongoose instalat, să creăm un nou author.js
fișier care va defini schema de autor și modelul:
var mongoose = necesită ("mongoose"); var autorSchema = mongoose.Schema (_id: mongoose.Schema.Types.ObjectId, nume: firstName: type: String, required: true, lastName: String, biografie: String, twitter: type: String, validate : validator: funcție (text) if (text! == null && text.length> 0) retur text.indexOf ('https://twitter.com/') === 0; : "Mânerul Twitter trebuie să înceapă cu https://twitter.com/ ', facebook: type: String, validate: validator: function (text) if (text! == null && text.length> 0) retur text.indexOf ('https://www.facebook.com/') === 0; return true;, mesaj: 'Pagina Facebook trebuie să înceapă cu https://www.facebook.com/', linkedin: type: String, validate: validator: function (text) if (text! == null && text.length> 0) retur text.indexOf ('https://www.linkedin.com/') = == 0; return true;, mesaj: "LinkedIn trebuie să înceapă cu https://www.linkedin.com/", profilePicture: Buffer, creat: type: Date, default: Date.now); var Autor = mongoose.model ("Autor", autorSchema); module.exports = Autor;
Cu schema de autor și modelul creat, permiteți trecerea la unelte și concentrarea asupra creării șablonului CSV care poate fi descărcat făcând clic pe linkul șablonului. Pentru a ajuta la generarea de șabloane CSV, voi folosi pachetul JSON în CSV. Să o instalăm acum:
npm instalează json2csv --save
Acum mă voi actualiza pe cel creat anterior index.js
fișier pentru a include o nouă ruta pentru "/ template":
var template = necesită ('./ template.js'); app.get ('/ template', template.get);
Am inclus doar noul cod pentru ruta șablonului care este adăugat la versiunea precedentă index.js
fişier.
Primul lucru pe care îl are acest cod este includerea unui nou template.js
fișier (care va fi creat în continuare) și să creați o rută pentru "/ template". Acest traseu va apela a obține
funcția în template.js
fişier.
Cu serverul Express actualizat pentru a include noul traseu, să creăm noul template.js
fişier:
var json2csv = cer ('json2csv'); exports.get = funcția (req, res) var fields = ['name.firstName', 'name.lastName', 'biografie', 'twitter', 'facebook', 'linkedin']; var csv = json2csv (data: ", fields: fields); res.set (" Content-Disposition " octet-stream "); res.send (csv);;
Acest fișier include mai întâi instalat anterior json2csv
pachet. Apoi, creez și export a obține
funcţie. Această funcție acceptă obiectele de solicitare și răspuns de pe serverul Express.
În interiorul funcției, am creat o serie de câmpuri pe care vreau să le includ în șablonul CSV. Acest lucru se poate face una din cele două căi. Primul mod (care se face în acest exemplu) este de a crea o listă statică a câmpurilor care vor fi incluse în șablon. A doua modalitate este de a crea dinamic lista de câmpuri prin extragerea proprietăților din schema de autor.
A doua modalitate se poate face cu următorul cod:
var fields = Object.keys (Autor.schema.obj);
Aș fi vrut să folosesc această metodă dinamică, dar devine puțin complicată atunci când nu vreau să includ mai multe proprietăți din schemă în șablonul CSV. În acest caz, șablonul meu nu include _id
și creată
deoarece acestea vor fi populate prin cod. Cu toate acestea, dacă nu aveți câmpuri pe care doriți să le excludeți, metoda dinamică va funcționa la fel.
Cu matricea de câmpuri definite, folosesc json2csv
pachet pentru a crea șablonul CSV din obiectul meu JavaScript. Acest csv
obiect va fi rezultatul acestui traseu.
Și, în final, folosind res
proprietate de la serverul Express, am setat două proprietăți antet care vor forța descărcarea unui authors.csv
fişier.
În acest moment, dacă ați rula aplicația Nod și navigați la http: // localhost în browserul dvs. web, formularul web va fi afișat cu un link pentru a descărca șablonul. Dacă faceți clic pe linkul pentru a descărca șablonul, veți putea descărca authors.csv
fișierul care urmează să fie populat înainte de a fi încărcat.
Iată un exemplu de fișier CSV populat:
nume.firstName, name.lastName, biografie, twitter, facebook, linkedin Jamie, Munro, Jamie este un dezvoltator web și autor ,,, Mike, Wilson, Mike este un dezvoltator web și autor Node.js,,,
Acest exemplu, când este încărcat, va crea doi autori: eu și un prieten care a scris o carte pe Node.js cu câțiva ani în urmă. Puteți observa că la sfârșitul fiecărei linii sunt trei virgule ",,,". Acest lucru se face pentru abrevierea exemplului. Nu am populat proprietățile rețelei sociale (stare de nervozitate
, Facebook
, și linkedin
).
Piesele de puzzle încep să se unească și formează o imagine. Să ajungem la carne și cartofi din acest exemplu și să analizăm fișierul CSV. index.js
fișierul necesită o actualizare pentru a vă conecta la MongoDB și pentru a crea un nou rute POST care va accepta încărcarea fișierului:
var app = necesită ('express') (); var fileUpload = necesită ('express-fileupload'); var mongoose = necesită ("mongoose"); serverul var = necesită ("http"). Server (app); app.use (fileUpload ()); server.listen (80); mongoose.connect ( 'MongoDB: // localhost / csvimport'); app.get ('/', funcția (req, res) res.sendFile (__ dirname + '/ index.html');); var template = necesită ('./ template.js'); app.get ('/ template', template.get); var upload = necesită ('./ upload.js'); app.post ('/', upload.post);
Cu o conexiune de baze de date și un nou traseu POST configurat, este timpul să analizăm fișierul CSV. Din fericire există mai multe biblioteci mari care ajută la acest loc de muncă. Am ales să folosesc fast-csv
pachet care poate fi instalat cu următoarea comandă:
npm instalează rapid-csv -save
Traseul POST a fost creat similar cu ruta șablonului care invocă a post
funcția de la upload.js
fişier. Nu este necesar să plasați aceste funcții în fișiere separate; cu toate acestea, îmi place să creez fișiere separate pentru aceste rute, deoarece ajută la păstrarea codului frumos și organizat.
Și, în sfârșit, să creăm upload.js
fișierul care conține fișierul post
funcție care se numește atunci când este trimis formularul creat anterior:
var csv = cer ('fast-csv'); var mongoose = necesită ("mongoose"); var Autor = cer ('./ autor'); exports.post = funcția (req, res) if (! req.files) return res.status (400) .send ('Nu au fost încărcate fișiere.'); var autorFile = req.files.file; var autori = []; csv .fromString (authorFile.data.toString (), headers: true, ignoreEmpty: true) .on ("date", funcția (data) data ['id'] = new mongoose.Types.ObjectId (); (date);)) .on ("end", function () autor.create (autori, functie (err, documente) if (err) throw err; + "au fost încărcați cu succes.");); ;
Un pic se întâmplă în acest fișier. Primele trei linii includ pachetele necesare care vor fi necesare pentru parsarea și salvarea datelor CSV.
Apoi, post
este definită și exportată pentru utilizare de către index.js
fişier. În interiorul acestei funcții se află unde are loc magia.
Funcția verifică mai întâi existența unui fișier conținut în corpul solicitării. Dacă nu există, se întoarce o eroare care indică faptul că trebuie încărcat un fișier.
Când un fișier a fost încărcat, o referință la fișier este salvată într-o variabilă numită authorFile
. Acest lucru se face accesând fișiere
array și fişier
proprietate în matrice. fişier
proprietatea se potrivește cu numele numelui de intrare al fișierului pe care l-am definit pentru prima dată în index.html
exemplu.
De asemenea, am creat un autori
array care va fi populate ca fișier CSV este analizat. Această matrice va fi utilizată pentru a salva datele în baza de date.
fast-csv
biblioteca este acum apelată prin utilizarea pârghiei fromString
funcţie. Această funcție acceptă fișierul CSV ca un șir. Am extras șirul din authorFile.data
proprietate. date
proprietatea conține conținutul fișierului meu CSV încărcat.
Am inclus două opțiuni la fast-csv
funcţie: antete
și ignoreEmpty
. Acestea sunt ambele setate Adevărat
. Acest lucru spune bibliotecii că prima linie a fișierului CSV va conține anteturile și că rândurile goale ar trebui ignorate.
Cu opțiunile configurate, am configurat două funcții de ascultători care sunt apelate atunci când date
eveniment și Sfârșit
evenimentul este declanșat. date
evenimentul se numește o dată pentru fiecare rând al fișierului CSV. Acest eveniment conține un obiect JavaScript al datelor analizate.
Actualizăm acest obiect pentru a include _id
proprietate a schemei de autor cu un nou objectId
. Acest obiect este apoi adăugat la autori
mulțime.
Atunci când fișierul CSV a fost analizat pe deplin, Sfârșit
evenimentul este declanșat. În cadrul funcției de apel invers, apelați crea
funcția pe modelul autorului, trecând matricea de autori
la el.
Dacă apare o eroare în încercarea de a salva matricea, se aruncă o excepție; în caz contrar, un mesaj de succes este afișat utilizatorului, indicând câte autori au fost încărcați și salvați în baza de date.
Dacă doriți să vedeți codul sursă complet, am creat un depozit GitHub cu codul.
În exemplul meu, am încărcat doar câteva înregistrări. Dacă cazul dvs. de utilizare necesită abilitatea de a încărca mii de înregistrări, ar fi o idee bună să salvați înregistrările în bucăți mai mici.
Acest lucru se poate face în mai multe moduri. Dacă aș fi implementat-o, aș sugera actualizarea date
funcția de apel invers pentru a verifica lungimea matricei de autori. Când matricea depășește lungimea definită, de ex. 100, sunați la Author.create
funcția pe matrice, apoi resetați matricea pentru a fi golită. Aceasta va salva apoi înregistrările în bucăți de 100. Asigurați-vă că părăsiți finala crea
apel în Sfârșit
funcția de apel invers pentru a salva înregistrările finale.
se bucura!