Bonjour,
J'aimerais mettre à jour une table de ma base de donnée via un fichier csv que j'upload depuis une page php.
J'ai regardé un peut sur le web mais ce que je trouve ne fonctionne pas chez moi, je pense que le problème viendrais de la taille du fichier.
Ce fichier fait 12Mo, j'ai réussi à faire un move_uploaded_file() mais le fichier est vide une foi déplacé.
Voici un bout de code :
if(isset($_FILES['csv'])) {
$dossier = ROOT . '/web/csv/';
$fichier = basename($_FILES['csv']['name']);
if (move_uploaded_file($_FILES['csv']['tmp_name'], $dossier . $fichier)) {
echo "Upload du fichier effectué avec succès !";
} else {
echo "Echec de l'upload !";
}
//Le chemin d'acces a ton fichier sur le serveur
$fichier = fopen($dossier . $_FILES['csv']['name'], "r");
//tant qu'on est pas a la fin du fichier :
while (!feof($fichier)) {
// On recupere toute la ligne
$uneLigne = addslashes(fgets($fichier));
//On met dans un tableau les differentes valeurs trouvés (ici séparées par un ';')
$tableauValeurs = explode(';', $uneLigne);
// On crée la requete pour inserer les donner (ici il y a 12 champs donc de [0] a [11])
var_dump($uneLigne);
// la ligne est finie donc on passe a la ligne suivante (boucle)
}
}else{
return $this->insert();
}
Je tiens à préciser (pas encore eu le temps de regarder) j'aimerais en lever la première ligne qui correspond à l'entête des colonnes.
Il y a beaucoup de colonne, lors de l'insert est ce que je dois indiquer toutes les colonnes? ou y a t-il une autre fonction pour le csv ?
Salut,
Je pense que ton problème sera résolu rapidement, mais je ne comprends pas en quoi un "LOAD DATA" ne fonctionnerait pas sur un mutualisé ?
Tu rapatrie ton fichier CSV sur ton serveur, puis tu fais un requête SQL "LOAD DATA LOCAL INFILE ''chemin/absolu/local/tonfichier.csv' INTO TABLE 'taTable' ... " (ne pas oublier le LOCAL !)
Tu as un paramètre pour enlever ta première ligne (IGNORE 1 LINES) - je te laisse regarder la doc de cette fonction ici : http://dev.mysql.com/doc/refman/5.7/en/load-data.html
En tout cas ça fonctionne sur du mutualisé OVH, et c'est beaucoup rapide ! surtout sur un mutualisé où les ressources peuvent être problématique, et tu n'as plus trop besoin de te soucier d'un problème qui pourrait arriver si ton fichier grossit (augmenter tes valeurs memory_limit etc ...)
Je pense que le soucis vient de ESCAPED BY '\\'.
Si tu copie ta requête est tu fait un echo, voilà ce que ça donne :
LOAD DATA INFILE ? INTO TABLE ftth_optimum FIELDS TERMINATED BY ';' ENCLOSED BY '"' ESCAPED BY '\' LINES TERMINATED BY '\r\n'
Donc il te faut rajouter deux \
dans ESCAPED BY
Ce qui donnerais :
LOAD DATA INFILE ? INTO TABLE ftth_optimum FIELDS TERMINATED BY ';' ENCLOSED BY '\"' ESCAPED BY '\\\\' LINES TERMINATED BY '\r\n'
Bonsoir,
Voila ce que moi j ai fais pour importer pas mal de donnees aussi:
ini_set('max_execution_time', 300); //300 seconds = 5 minutes
if( isset($_FILES['import']) ){
// Disons que je veux mettre mon fichier dans le dossier imports qui est dans le dossier courant
// Créé le nom du fichier:
$filename = __DIR__ . "/imports/".basename($_FILES['import']['name']) ;
// Place le fichier, sous le nom que je viens de lui donner, dans le répertoire approprié
move_uploaded_file( $_FILES['import']['tmp_name'], $filename);
// fonction lecture du fichier
function read_csv($filename){
// ouverture du fichier
$FILE=fopen($filename,"r");
// lire ligne par ligne et couper colonne par colonne
while ($ARRAY[]=fgetcsv($FILE,1024,";"));
// fermer le fichier
fclose($FILE) ;
// effacer la dernière ligne
array_pop($ARRAY);
// renvoi le tableau
return $ARRAY ;
}
$data = read_csv($filename);
foreach ( array_slice( $data, 1 ) as $i => $line ) {
esperant que cela puisse te servir
Gilles
Bon mon problème c'est que je ne passe pas la première condition :
if(isset($_FILES['csv'])) {}
Je ne comprend pas, je fais un simple formulaire
<div class="col-sm-12">
<form method="post" enctype="multipart/form-data">
<?= $form->input('csv', 'Fichier CSV', ["type" => "file"], true);?>
<button type="submit" class="btn btn-success">Valider</button>
</form>
</div>
$form->imput fait appel a une classe qui génére le formulaire (nom, label, option->type, require)
Donc je ne comprends pas ! c'est à dire que je charge mon fichier, lorsque je valide, le fichier disparait en faisant des tests, je n'ai pas de fichier !
Bon là je suis dans le floue !!!
j'ai mon input de type file avec name=csv
Dans mon controller, j'ai fait une condition pour voir si je recevais bien une method post, ce qui est le cas !
Juste derrière, je fais un var_dump($_FILES['csv']); die;
j'obtiens une belle erreur Undefined index: csv
Si quelqu'un a une idée !!!???
Hello,
Dans un premier temps, essai d'uploader un petit fichier.
A mon avis, tu as un soucis de taille. Vérifie ta configuration PHP si tu as un upload_max_filesize et post_max_size défini a 12M (ou plus).
Par contre, cela devrait t'afficher une erreur. As tu activé l'affichage des erreurs ?
Ok c'est bien ça, mais je suis sous wamp donc facile a configurer, mais sur un hebergement ovh comment fait-on?
Si tu es sur un mutualisé, il va falloir aller voir avec PHPINFO() la taille définie. Il ne me semble pas que tu puisse le modifier.
Par contre, si tu prend un dédié, tu fais ce que tu veux avec, donc pas de soucis de ce côté là.
Bon autre problème, J'ai un problème mémoire lorsque je rentre dans cette boucle
while ($ARRAY[]=fgetcsv($FILE,1024,";"));
llowed memory size of 536870912 bytes exhausted
Mon fichier csv doit contenir un peut plus de 1000 lignes
Il s'agit d'un soucis d'allocation mémoire. Il faut changer ton param memory_limit du PHP.ini.
Bon une dernière question, une foi à cette étape :
foreach ( array_slice( $data, 1 ) as $i => $line ) {}
Je dois inserer en base de donnée les résultats.
dans mon var_dump($i, $line); j'obtiens :
array (size=21626)
0 =>
array (size=71)
0 => string 'dossier' (length=7)
1 => string 'zone_arcep_site' (length=15)
2 => string 'num_asoeie' (length=10)
3 => string 'code_regroupement_syndic' (length=24)
4 => string 'nb_logements_du_regroupement' (length=28)
5 => string 'id_pm' (length=5)
6 => string 'site_hebergeant_le_pmi' (length=22)
7 => string 'type_de_pm' (length=10)
8 => string 'etat_de_pm' (length=10)
9 => string 'date_etat_pm' (length=12)
10 => string 'date_construction_pm' (length=20)
11 => string 'zone_arcep_pm' (length=13)
12 => string 'numero_de_lot' (length=13)
13 => string 'id_pa' (length=5)
14 => string 'etat_de_pa' (length=10)
15 => string 'identifiant_processus' (length=21)
16 => string 'type_processus_particulier' (length=26)
17 => string 'cle_du_site_calculee' (length=20)
18 => string 'cle_du_site_reelle' (length=18)
19 => string 'densite_iris' (length=12)
20 => string 'code_iris' (length=9)
21 => string 'date_maj_contour' (length=16)
22 => string 'num' (length=3)
23 => string 'num_cplt' (length=8)
24 => string 'voie' (length=4)
25 => string 'adresse' (length=7)
26 => string 'batiment' (length=8)
27 => string 'escalier' (length=8)
28 => string 'cp' (length=2)
29 => string 'localite' (length=8)
30 => string 'rivoli' (length=6)
31 => string 'operateur_immeuble' (length=18)
32 => string 'etat_negociation' (length=16)
33 => string 'etat_technique' (length=14)
34 => string 'etat_site' (length=9)
35 => string 'site_sature' (length=11)
36 => string 'site_bloque' (length=11)
37 => string 'seuil_prospects' (length=15)
38 => string 'type_site' (length=9)
39 => string 'presence_concurrent' (length=19)
40 => string 'date_de_construction' (length=20)
41 => string 'dlpi' (length=4)
42 => string 'detection_zlin' (length=14)
43 => string 'type_de_commercialisation' (length=25)
44 => string 'etat_zlin' (length=9)
45 => string 'j3m' (length=3)
46 => string 'fttdp' (length=5)
47 => string 'preequipe' (length=9)
48 => string 'taille_site' (length=11)
49 => string 'code_taille_site' (length=16)
50 => string 'nb_logements' (length=12)
51 => string 'nb_logements_r' (length=14)
52 => string 'nb_logements_p' (length=14)
53 => string 'taux_de_penetration_net' (length=23)
54 => string 'taux_de_penetration_brut' (length=24)
55 => string 'nb_escaliers' (length=12)
56 => string 'nb_etages' (length=9)
57 => string 'premier_dem_pap' (length=15)
58 => string 'dernier_dem_pap' (length=15)
59 => string 'nb_demarchages_pap' (length=18)
60 => string 'date_dern_isa' (length=13)
61 => string 'suivi_strategique_upr' (length=21)
62 => string 'marquage_temporaire_upr' (length=23)
63 => string 'annee_programme' (length=15)
64 => string 'potentiel_immeuble' (length=18)
65 => string 'immeuble_prioritaire' (length=20)
66 => string 'typologie' (length=9)
67 => string 'presence_vip' (length=12)
68 => string 'etat_acces_immeuble' (length=19)
69 => string 'envoi_commande_acces_immeuble' (length=29)
70 => string 'v' (length=1)
Donc je dois déjà supprimer cette ligne qui correspond aux entête de ma table et surtout comment faire pour ne pas a devoir taper les champs à remplir, il y en a 70 :(
Un conseil, ne met pas une valeur au pifomètre ... 900M de mémoire a alloué, ca commence à faire beaucoup.
Joue un peu avec réduit jusqu'a temps d'avoir une erreur, et augmente un peu après histoire de prendre une marge de sécurité.
En ce qui concerne ta question, une petite recherche sur le net rapidement t'aurais donné la solution :
http://stackoverflow.com/questions/578037/how-do-i-remove-the-top-line-in-a-csv-file-the-coloumn-headers
Ok en faisant les tests, 600M correspond à la limite !
pour la solution que tu m'as donné, en fait ça n'ai pas vraiment le problème là que je souhaitais mettre en avant, mais le fait de faire un insert avec 70 colones a renseigner ! mais de toute façon je pense ne pas avoir le choix !
Pour finir, je te conseil de lire ceci : http://www.developpez.net/forums/d1184103/php/php-sgbd/php-mysql/importer-csv-php-bdd/
En effet, l'import en ligne de commande, permettrait de ne pas pomper toute la RAM de ton serveur (ca pompera moins en tout cas).
Après, si tu es sur un mutualisé, ce n'est pas possible.
Si ton sujet est résolu, n'hésite pas à marquer la / les réponses qui t'ont aidés.
Oui je l'avais vue ! Seulement je suis sur un mutualisé.
Je fais encore 2 ou 3 tests et je passe en résolu !
En fait j'ai un autre problème, c'est que lors de mon var_dump($i, $line); je me rends compte que la colone 70 est incomplète. v au lieu de validation. de plus après cette ligne, il y a encore pas mal de colone !
Comme je l'ai dit, c'est une grosse table, une table dont je n'ai que accès par export csv :(
Bon j'ai essayé avec LOAD DATA.
J'essaie de l'incorporer à mon model MVC vue sur ce site. Seulement j'ai une erreur du type
PDOStatement::execute(): LOAD DATA LOCAL INFILE forbidden
j'ai vue sur certain forum que le LOCAL peut poser problème, dans mon cas, j'obtiens une autre erreur si je l'enlève.
Bon je progresses mais pas encore eu le resultat que je cherches !
J'arrives à mettre les données dans la bdd, seulement j'ai uniquement la première colone de remplit, le reste est a NULL.
Pour info, lorsque j'importe le fichier directement depuis phpmyadmin, ça se passe très bien ! Une idée?
Vérifie tes séparateurs qu'ils correspondent bien à tes paramètres de la requete, exemple :
LOAD DATA LOCAL INFILE '/path.csv' INTO TABLE table FIELDS TERMINATED BY "," LINES TERMINATED BY "\n";
Sinon, bien vérifier que les colonnes correspondent trait pour trait au CSV.
pfffff ça m'agasse de tomber a chaque foi sur un prob !!!
Voici la requette qui fonctionne dans phpmyadmin :
LOAD DATA INFILE 'C:\\wamp\\tmp\\phpBC1E.tmp' INTO TABLE `ftth_optimum` FIELDS TERMINATED BY ';' ENCLOSED BY '"' ESCAPED BY '\\' LINES TERMINATED BY '\r\n'# 21624 lignes affectées.
mon code
return $this->query(
"LOAD DATA INFILE ? INTO TABLE ftth_optimum FIELDS TERMINATED BY ';' ENCLOSED BY '\"' ESCAPED BY '\\' LINES TERMINATED BY '\r\n'", [$file]
);
pour ENCLOSED BY '\"' j'echape la double quote je ne sais pas si ça vient de là mais j'ai une erreur de syntax
Franchement merci de ton aide, je n'avais pas pensé à regarder en faisant un echo ! Du coup tout fonctionne, je peux enfin avancer !!! Merci beaucoup.