Requette "different de .."

Par Lea42, il y a 7 ans


Hello :)

J ai crée un systeme de traitement de fichier.

Ce que je veut c est que via une interface, l'utilisateur pose son csv via un input type file. Je souhaiterais que lorsqu'il pose son csv, le csv soit comparer avec ce qu'il y a dans la BDD, si ont trouve des mail dans le fichier csv qui sont identique avec des mail qu il y a dans la BDD alors ont supprime ce doublon du CSV, a la fin de ce traitement, je souhaiterais que le fichier soit retournée a l'utilisateur (qu il puisse le télécharger) sans les doublon ;)

Par exemple dans ma BDD j ai : toto@gmail, titi@gmail.com
Dans la fichier que je vais upload j ai : toto@gmail, titi@gmail.com, tutu@gmail.com

Quand je récupère mon fichier upload après qu il a était comparée dans la BDD je veut qu il reste que : tutu@gmail.com

Et je bloque sur la partie ou ont traite les doublons .. j ai chercher sur pleins de site et de forum et je n ai pas trouver de solution, ca fait un moment que je suis sur ce bug et cette outil doit etre livrer dans les temps .. :(

<?php // V�rifie si la chaine ressemble � un email //if (filter_var($email, FILTER_VALIDATE_EMAIL)) { // echo 'Cet email est correct.'; //} else { // echo 'Cet email a un format non adapt�.'; //} echo "coucou"; $dossier = 'upload/'; //* Je cr�e un dossier pour herberger mes fichier temporaire $fichier = basename($_FILES['fileup']['name']); //$taille_maxi = 200000; $taille = filesize($_FILES['fileup']['tmp_name']); $extensions = array('.csv', '.txt'); //*Je cr�e mes extentions $extension = strrchr($_FILES['fileup']['name'], '.'); $import=$_POST['import']; $ignore=($_POST['ignore']); $delimiter = $_POST['delimiteur']; $separateur = $_POST['separateur']; //D�but des v�rifications de s�curit�... if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau { $erreur = ''; } //if($taille>$taille_maxi) //{ // $erreur = 'Le fichier est trop gros...'; //} if(!isset($erreur)) //S'il n'y a pas d'erreur, on upload { //On formate le nom du fichier ici... $fichier = strtr($fichier, '����������������������������������������������������', 'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy'); $fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier); if(move_uploaded_file($_FILES['fileup']['tmp_name'], $dossier . $fichier)){ // Je lis mon fichier csv $row = 1; if (($handle = fopen("upload/".$fichier, "r")) !== FALSE) { while (($data = fgetcsv($handle, 1000, $separateur, $delimiter)) !== FALSE) { if ($row > $ignore){ $num = count($data); // print_r($data); if (filter_var($data[$import], FILTER_VALIDATE_EMAIL)){ //Je filtre les mail si le mail est ok alors je lance la requete $requette = $db->prepare("SELECT `hardbounce_email` FROM `hardbounce` WHERE `hardbounce_email` != ".$data[$import]." "); $requette->execute(); $resultat = $requette->fetchAll(PDO::FETCH_ASSOC); //Ouverture d'un nouveau fichier $chemin = $_POST['chemin'].".csv"; if(!empty($resultat)){ $fichier_csv = fopen("import/".$chemin, 'w+'); fprintf($fichier_csv, chr(0xEF).chr(0xBB).chr(0xBF)); //Pour les caractere speciaux de excel // fermeture du nouveau fichier csv $lignes[] = array($data[$import]) ; // Boucle foreach sur chaque ligne du tableau foreach($lignes as $key => $valeur){ $newhandle=fputcsv($fichier_csv, $valeur, $delimiter); } fclose($fichier_csv); } } } $row++; } echo '<div class="lien">Le fichier a etait traiter ! </br> Il y a eu <span class="green"> '.$row.' ligne </span> traiter </br> <a href="import/'.$chemin.'">Telecharger le fichier</a></div> '; fclose($handle); } // echo '<div class="container-fluid">' // . '<div class="row">' // . '<div class="col-lg-12 sucess_envoi">' // . '<span class="">Upload effectu� avec succ�s!</span><span class="btn-liste"><a href="index.php?nav=ListeHardbounce.php"> Voir la liste </a></span>' // . '</div>' // . '</div>' // .'</div>'; }else{ echo '<span class="echec_envoi">Echec de l\'upload !</span>'; } } else { echo $erreur; } ?>

22 réponses

SNOWWTARIE, il y a 7 ans

Yep, my bad.
J'ai pas pris en compte le fait que le PDOStatement est une sorte de tableau de tableaux. Du coup il ne vérifie jamais l'email. Il suffit d'en faire un tableau de tous les résultats.
Essaye d'ajouter ça :

$resultats = $db->query("SELECT DISTINCT `hardbounce_email` FROM `hardbounce`", PDO::FETCH_NUM); $resultats = $resultats->fetchAll(PDO::FETCH_COLUMN);

A la place de la query actuelle.

Lartak, il y a 7 ans

Bonjour.
Première chose que je ne comprends pas, si c'est pour analyser que des CSV, pourquoi accepter des fichiers de type TXT ?
Ensuite, pour récupérer l'extension d'un fichier, tu peux par exemple faire :

$extension = pathinfo($_FILES['fileup']['tmp_name'], PATHINFO_EXTENSION);
Lea42, il y a 7 ans

Hello, merci pour ta reponse Lartak, mais du coup j ai reussi a resoudre mon probleme :)
Mais du coup je suis face a deux beug:

1) Je ne peut pas mettre de fichier lourd sinon ca plante

2) Ca ne traitre que les fichier ou il y a que des adresses mail et c est problematique parce que souvent dans les fichier il y a : "toto@gmail.com";"toto";"tutu";"21 rue des tyty";"42100";"tata";"0654789512"

Lea42, il y a 7 ans
$dossier = '/var/www/repoussoir/upload/'; //* Je cr�e un dossier pour herberger mes fichier temporaire $fichier = basename($_FILES['fileup']['name']); $fileTmpName = $_FILES['fileup']['tmp_name']; $taille_maxi = 0; $taille = filesize($_FILES['fileup']['tmp_name']); $extensions = array('.csv', '.txt'); //*Je cr�e mes extentions $extension = strrchr($_FILES['fileup']['name'], '.'); $import=$_POST['import']; //numeros du champ du CSV qui correspond au champ mail $ignore=($_POST['ignore']); $delimiter = $_POST['delimiteur']; $separateur = $_POST['separateur']; //D�but des v�rifications de s�curit�... if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau { $erreur = ''; } //if($taille>$taille_maxi) //{ // $erreur = 'Le fichier est trop gros...'; //} if(!isset($erreur)) //S'il n'y a pas d'erreur, on upload { //On formate le nom du fichier ici... $fichier = strtr($fichier, '����������������������������������������������������', 'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy'); $fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier); if(move_uploaded_file($fileTmpName, $dossier.$fichier)) { // Je lis mon fichier csv $row = 1; // $handle = fopen($dossier.$fichier, "r"); if (($handle = fopen($dossier.$fichier, "r")) !== FALSE) { // $data = fgetcsv($handle, $taille_maxi, $separateur, $delimiter); // while ($data !== FALSE) while (($data = fgetcsv($handle, $taille_maxi, $separateur, $delimiter)) !== FALSE) { if ($row > $ignore) { $num = count($data); // print_r($data); if (filter_var($data[$import], FILTER_VALIDATE_EMAIL)) { //Je filtre les mail si le mail est ok alors je lance la requete $requette = $db->prepare("SELECT * FROM `hardbounce` WHERE `hardbounce_email` = '".$data[$import]."'"); $requette->execute(); $resultat = $requette->fetchAll(PDO::FETCH_ASSOC); //Ouverture d'un nouveau fichier $chemin = $_POST['chemin'].".csv"; if(empty($resultat)) { $lignes = array($data); } } } $row++; } if(!empty($lignes)) { $fichier_csv = fopen("/var/www/repoussoir/import/".$chemin, 'w+'); fprintf($fichier_csv, chr(0xEF).chr(0xBB).chr(0xBF)); //Pour les caractere speciaux de excel // Boucle foreach sur chaque ligne du tableau foreach($lignes as $key => $valeur) { $newhandle=fputcsv($fichier_csv, $valeur, $delimiter); } fclose($fichier_csv); } echo '<div class="lien">Le fichier a etait traiter ! :) </br> Il y a eu <span class="green"> '.$row.' ligne </span> traiter </br> <a href="import/'.$chemin.'">Telecharger le fichier</a></div> '; fclose($handle); } }else{ echo '<span class="echec_envoi">Echec de l\'upload !</span>'; } } else { echo $erreur; } ?>
SNOWWTARIE, il y a 7 ans

Pour la taille des fichiers, essaye de mettre à jour ton php.ini (https://stackoverflow.com/questions/3829403/how-to-increase-the-execution-timeout-in-php).
Pour le traitement, ne jamais faire confiance à l'utilisateur (dans ton script tu pars du principe que l'adresse mail sera toujours le N ème champ de ton CSV. Mais si l'utilisateur ne sait pas qu'il doit compter à partir de 0, tu es bloquée. Gère chaque ligne indépendamment, quitte à boucler sur chaque ligne et anisi être sûr de ne traiter que les emails.
Autre petit points, tu fais autant de SELECT que de lignes ayant un email valide. Pourquoi ne pas faire une requête une fois le fichier ouvert ? SELECT DISTINCT hardbounce_email FROM hardbounce

Lea42, il y a 7 ans

Je vais essayer, tu as raison surtout que ca lague beaucoup comme j ai fait ! :)

Lea42, il y a 7 ans

Et du coup en faisant comme ca, si dans mon fichier il n'y a pas que des adresse mail, ca passeras quand meme ? :)

SNOWWTARIE, il y a 7 ans

Si tu fais un truc genre
foreach ($data as $value) { if (filter_var($value, FILTER_VALIDATE_EMAIL)) { $email = $value; break; } }

Tu n'auras que ton email à chaque fois. Sauf si dans ton fichier tu as une ligne avec deux email. Dans ce cas, plutôt faire un truc du style :
$emails = []; foreach ($data as $value) { if (filter_var($value, FILTER_VALIDATE_EMAIL)) $emails[] = $value; }

(Désolé j'arrive pas à mettre les tabulations, j'ai du mal avec le WYSIWYG)

Lea42, il y a 7 ans

Du coup j ai fait ta deuxieme proposition, mais ne m affiche un page vide j en je telecharge le fichier qui a etait traiter :(

ps : merci a toi de m aider, c est trop frustrant de ce retrouver seule face a des bugs ^^

$dossier = '/var/www/repoussoir/upload/'; //* Je cr�e un dossier pour herberger mes fichier temporaire $fichier = basename($_FILES['fileup']['name']); $fileTmpName = $_FILES['fileup']['tmp_name']; $taille_maxi = 0; $taille = filesize($_FILES['fileup']['tmp_name']); $extensions = array('.csv', '.txt'); //*Je cr�e mes extentions $extension = strrchr($_FILES['fileup']['name'], '.'); $import=$_POST['import']; //numeros du champ du CSV qui correspond au champ mail $ignore=($_POST['ignore']); $delimiter = $_POST['delimiteur']; $separateur = $_POST['separateur']; //D�but des v�rifications de s�curit�... if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau { $erreur = ''; } if(!isset($erreur)) //S'il n'y a pas d'erreur, on upload { //On formate le nom du fichier ici... $fichier = strtr($fichier, '����������������������������������������������������', 'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy'); $fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier); if(move_uploaded_file($fileTmpName, $dossier.$fichier)) { // Je lis mon fichier csv $row = 1; // $handle = fopen($dossier.$fichier, "r"); if (($handle = fopen($dossier.$fichier, "r")) !== FALSE) { // $data = fgetcsv($handle, $taille_maxi, $separateur, $delimiter); // while ($data !== FALSE) while (($data = fgetcsv($handle, $taille_maxi, $separateur, $delimiter)) !== FALSE){ if ($row > $ignore) { $num = count($data); // print_r($data); if (filter_var($data[$import], FILTER_VALIDATE_EMAIL)) { //Je filtre les mail si le mail est ok alors je lance la requete $requette = $db->prepare("SELECT DISTINCT hardbounce_email FROM hardbounce WHERE `hardbounce_email` = '".$data[$import]."'"); $requette->execute(); $resultat = $requette->fetchAll(PDO::FETCH_ASSOC); //Ouverture d'un nouveau fichier $chemin = $_POST['chemin'].".csv"; if(empty($resultat)) { $lignes = $data; } } } $row++; } if(!empty($lignes)) { $fichier_csv = fopen("/var/www/repoussoir/import/".$chemin, 'w+'); fprintf($fichier_csv, chr(0xEF).chr(0xBB).chr(0xBF)); //Pour les caractere speciaux de excel // Boucle foreach sur chaque ligne du tableau $emails = []; foreach ($data as $value) { if (filter_var($value, FILTER_VALIDATE_EMAIL)) $emails[] = $value; } fclose($fichier_csv); } echo '<div class="lien">Le fichier a etait traiter ! :) </br> Il y a eu <span class="green"> '.$row.' ligne </span> traiter </br> <a href="import/'.$chemin.'">Telecharger le fichier</a></div> '; fclose($handle); } }else{ echo '<span class="echec_envoi">Echec de l\'upload !</span>'; } } else { echo $erreur; }
SNOWWTARIE, il y a 7 ans
<?php $dossier = '/var/www/repoussoir/upload/'; //* Je cr�e un dossier pour herberger mes fichier temporaire $fichier = basename($_FILES['fileup']['name']); $fileTmpName = $_FILES['fileup']['tmp_name']; $taille_maxi = 0; $taille = filesize($_FILES['fileup']['tmp_name']); $extensions = array('.csv', '.txt'); //*Je cr�e mes extentions $extension = strrchr($_FILES['fileup']['name'], '.'); $import=$_POST['import']; //numeros du champ du CSV qui correspond au champ mail $ignore=($_POST['ignore']); $delimiter = $_POST['delimiteur']; $separateur = $_POST['separateur']; //D�but des v�rifications de s�curit�... if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau { $erreur = ''; } //if($taille>$taille_maxi) //{ // $erreur = 'Le fichier est trop gros...'; //} if(!isset($erreur)) //S'il n'y a pas d'erreur, on upload { //On formate le nom du fichier ici... $fichier = strtr($fichier, '����������������������������������������������������', 'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy'); $fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier); if(move_uploaded_file($fileTmpName, $dossier.$fichier)) { // Je lis mon fichier csv $row = 1; // $handle = fopen($dossier.$fichier, "r"); if (($handle = fopen($dossier.$fichier, "r")) !== FALSE) { // On récupère tous les emails de manière distincte afin de vérifier ligne par ligne si l'email n'existe pas déjà // Pas besoin de requête paramétrée vu qu'on n'a plus de saisie utilisateur $resultats = $db->query("SELECT DISTINCT `hardbounce_email` FROM `hardbounce`"); // Cette variable va me permettre de stocker les données que je veux enregistrer $lignes = []; while (($data = fgetcsv($handle, $taille_maxi, $separateur, $delimiter)) !== FALSE) { if ($row > $ignore) { // Boucle foreach sur chaque cellule de la ligne CSV afin de vérifier l'email foreach ($data as $value) { $exists = false; // Si la cellule est un email valide if (filter_var($value, FILTER_VALIDATE_EMAIL)) { // On vérifie si elle existe déjà en base d'après le résultat de notre requête if (in_array($value, $resultats)) { // Si on a déjà l'email, on ne l'ajoute pas à nos lignes $exists = true; break; } } if (!$exists) { $lignes[] = $data; } } } $row++; } if(!empty($lignes)) { $chemin = $_POST['chemin'].".csv"; $fichier_csv = fopen("/var/www/repoussoir/import/".$chemin, 'w+'); fprintf($fichier_csv, chr(0xEF).chr(0xBB).chr(0xBF)); //Pour les caractere speciaux de excel $lignes[] = array($data[$import]) ; // Boucle foreach sur chaque ligne du tableau foreach($lignes as $valeur){ $newhandle=fputcsv($fichier_csv, $valeur, $delimiter); } fclose($fichier_csv); } echo '<div class="lien">Le fichier a etait traiter ! :) </br> Il y a eu <span class="green"> '.$row.' ligne </span> traiter </br> <a href="import/'.$chemin.'">Telecharger le fichier</a></div> '; fclose($handle); } } else { echo '<span class="echec_envoi">Echec de l\'upload !</span>'; } } else { echo $erreur; }

J'ai un peu modifié ton code (si j'ai bien compris ce que tu voulais faire avec) et j'ai commenté pour que tu puisses comprendre mais globalement :

  1. Je récupère toutes les adresses emails depuis hardbounce
  2. Je boucle sur chaque ligne du CSV
  3. Je boucle sur chaque "cellule" du CSV afin de vérifier l'email de la ligne (si il y en a un). Si on a un email valide et non présent en base, on conserve la ligne
  4. Si j'ai des lignes à conserver, je créé mon nouveau fichier

Je ne suis pas sûr de moi mais si le but est de supprimer du CSV les lignes ayant un email déjà présent en base, çe devrait le faire.

Lea42, il y a 7 ans

Roooh t es trop fort toi merci :D
Du coup j arrive ENFIN a recuperer toute la ligne de mon fichier, avec le mail, le nom, le prenom ,... ca c est vraiment top! :D Mais du coup ca ne supprime plus doublons :p

Lea42, il y a 7 ans

Dans mon fichier .csv j'ai:

toto@gmail.com yuyu toto tata
leana.dutrou4545@hotmail,com leana dutrou ** 10 rue de la breche

toto est deja dans ma BDD du coup je supprimer toute la ligne
leana n est pas dans ma BDD du coup je garde toute la ligne

  • Encore merci de m aider t es super !! :D
Lea42, il y a 7 ans

Hum non toujours pas, normalement ca devrais pas etre plutot:

$resultats = $db->query("SELECT DISTINCT `hardbounce_email` FROM `hardbounce`", PDO::FETCH_NUM); $result = $resultats->fetchAll(PDO::FETCH_COLUMN);

et apres dans le if:

if (in_array($value, $result)) { // Si on a déjà l'email, on ne l'ajoute pas à nos lignes $exists = true; break; }

Tu en pense quoi ? :)

Lea42, il y a 7 ans

Ah c est tellement fustrant ont y est preeeeeeesque :D

SNOWWTARIE, il y a 7 ans

Une erreur de ma part dans le code que je t'ai donné, j'ai l'ajout de dans la ligne dans la vérification des différentes données de la ligne (le foreach). Ce qui fait que si l'email n'est pas la première donnée, on ajoute la ligne quoi qu'il arrive.
Ce qui nous donne

<?php $dossier = '/var/www/repoussoir/upload/'; //* Je cr�e un dossier pour herberger mes fichier temporaire $fichier = basename($_FILES['fileup']['name']); $fileTmpName = $_FILES['fileup']['tmp_name']; $taille_maxi = 0; $taille = filesize($_FILES['fileup']['tmp_name']); $extensions = array('.csv', '.txt'); //*Je cr�e mes extentions $extension = strrchr($_FILES['fileup']['name'], '.'); $import=$_POST['import']; //numeros du champ du CSV qui correspond au champ mail $ignore=($_POST['ignore']); $delimiter = $_POST['delimiteur']; $separateur = $_POST['separateur']; //D�but des v�rifications de s�curit�... if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau { $erreur = ''; } //if($taille>$taille_maxi) //{ // $erreur = 'Le fichier est trop gros...'; //} if(!isset($erreur)) //S'il n'y a pas d'erreur, on upload { //On formate le nom du fichier ici... $fichier = strtr($fichier, '����������������������������������������������������', 'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy'); $fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier); if(move_uploaded_file($fileTmpName, $dossier.$fichier)) { // Je lis mon fichier csv $row = 1; // $handle = fopen($dossier.$fichier, "r"); if (($handle = fopen($dossier.$fichier, "r")) !== FALSE) { // On récupère tous les emails de manière distincte afin de vérifier ligne par ligne si l'email n'existe pas déjà // Pas besoin de requête paramétrée vu qu'on n'a plus de saisie utilisateur $resultats = $db->query("SELECT DISTINCT `hardbounce_email` FROM `hardbounce`"); // Cette variable va me permettre de stocker les données que je veux enregistrer $lignes = []; while (($data = fgetcsv($handle, $taille_maxi, $separateur, $delimiter)) !== FALSE) { $exists = false; if ($row > $ignore) { // Boucle foreach sur chaque cellule de la ligne CSV afin de vérifier l'email foreach ($data as $value) { // Si la cellule est un email valide if (filter_var($value, FILTER_VALIDATE_EMAIL)) { // On vérifie si elle existe déjà en base d'après le résultat de notre requête if (in_array($value, $resultats)) { // Si on a déjà l'email, on ne l'ajoute pas à nos lignes $exists = true; break; } } } if (!$exists) { $lignes[] = $data; } } $row++; } if(!empty($lignes)) { $chemin = $_POST['chemin'].".csv"; $fichier_csv = fopen("/var/www/repoussoir/import/".$chemin, 'w+'); fprintf($fichier_csv, chr(0xEF).chr(0xBB).chr(0xBF)); //Pour les caractere speciaux de excel $lignes[] = array($data[$import]) ; // Boucle foreach sur chaque ligne du tableau foreach($lignes as $valeur){ $newhandle=fputcsv($fichier_csv, $valeur, $delimiter); } fclose($fichier_csv); } echo '<div class="lien">Le fichier a etait traiter ! :) </br> Il y a eu <span class="green"> '.$row.' ligne </span> traiter </br> <a href="import/'.$chemin.'">Telecharger le fichier</a></div> '; fclose($handle); } } else { echo '<span class="echec_envoi">Echec de l\'upload !</span>'; } } else { echo $erreur; }

Et pour le fetchAll, pas besoin d'une nouvelle variable, la façon dont est gérée la mémoire en PHP permet ce genre de fantaisie.

Par contre tu feras attention tu as mis un numéro de portable en exemple de CSV, fais attention ;)

Lea42, il y a 7 ans

Aaah merci ca marche niiiiickel ! Tu gere ! :D

Lea42, il y a 7 ans

Par contre par rapport au poid du fichier, le conseille que tu m as donner c est pour du local et moi je suis en prod :p

SNOWWTARIE, il y a 7 ans

Ca marche aussi en prod, il faut juste modifier le fichier php.ini sur le serveur de production ;)

Lea42, il y a 7 ans

Oui mais c est sur un serveur sous linux ca marche aussi ? ^^ ( mes connaissance en serveur sont nul :p )

SNOWWTARIE, il y a 7 ans

Si tu es sur windows ton WAMP/XAMPP n'est là que pour "émuler" un serveur (apache le plus souvent) car Apache n'existe pas sur Windows. Donc pour répondre à ta question oui, ton serveur linux a un php.ini :)