2016-04-19 5 views
2

Ich muss eine große CSV nach MySQL hochladen, wenn ich Pausen hochladen muss, muss ich an der Stelle beginnen, wo ich aufgehört habe, keine doppelten Einträge. Wenn Prozess bricht dann sollte es neu starten, von wo ich automatisch beendet (dh: wenn das Hochladen Pause nach 123 Einträge dann sollte es von 124 auf den nächsten Lauf wieder aufnehmen)Wie lade ich eine große CSV-Datei mit PHP ohne doppelte Einträge in MySQL hoch?

CSV-Dateiformat:

latitude longitude 
6.5486 72.456 
4.2186 74.466 
5.5486 82.956 

ich nur brauchen ein Eintrag mit dem gleichen Längen- und Breitengrad, momentan benutze ich den unten stehenden Code (funktioniert), aber ich weiß nicht, wie ich vom Bruchpunkt anfangen soll, wenn ich Pausen einlege.

<?php 
error_reporting(0); 
require("connection.php");//connect to the database 
if ($_FILES[csv][size] > 0){ 
    //get the csv file 
    $file = $_FILES[csv][tmp_name]; 
    echo $fname = $_FILES['csv']['name']; 
    echo $ftype = end(explode('.', strtolower($fname))); 
    if($ftype=="csv"){ 
     $handle = fopen($file,"r"); 
     //loop through the csv file and insert into database 
     do { 
     if ($data[0]) { 
     $latitude=$data[0]; 
     $longitude=$data[1]; 
     $location1=$data[2]; 
     $location2=$data[3]; 
     $location3=$data[4]; 
     $sql = "SELECT * FROM latitude_longitude WHERE latitude ='$latitude' AND longitude='$longitude' "; 
     $result=mysql_query($sql); 
     if(mysql_num_rows($result) > 0){ 
      mysql_query("UPDATE latitude_longitude SET latitude = '$latitude',longitude = '$longitude',location1='$location1', location2='$location2',location3='$location3',status=status+1 WHERE latitude = '$latitude' AND longitude = '$longitude'"); 
     } 
     else{ 
      mysql_query("INSERT INTO latitude_longitude (latitude, longitude, location1, location2, location3, status, date) VALUES 
      ( 
       '".addslashes($data[0])."', 
       '".addslashes($data[1])."', 
       '".addslashes($data[2])."', 
       '".addslashes($data[3])."', 
       '".addslashes($data[4])."', 
       '1', 
       CURRENT_TIMESTAMP 
      ) 
     "); 
     } 
     } 
     } while ($data = fgetcsv($handle,1000,",","'")); 
     //redirect 
     header('Location:GeoLocation.php?success=1'); die; 

    }else{ 
     header('Location:GeoLocation.php?success=2'); die; 

    } 
} 
?> 

danke für die Hilfe im Voraus.

+0

Erstellen Sie einen eindeutigen Schlüssel auf Länge, Breite Sie können etwas wie unten verwenden – Priyanshu

Antwort

1

Erstellen Sie einzigartige Schlüssel auf Länge, Breite

und dann können Sie so etwas wie unten

LOAD DATA LOCAL INFILE 'c:\\temp\\filename.csv' 
replace 
INTO TABLE table_name 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\r\n' 
IGNORE 1 LINES 
(@col1,@col2,@col3) 
set 
column1 = @col1, 
column2= @col2, 
column3= @col3; 

diese doppelte lange ersetzen verwenden, lat und fügen neue

0

Hinweis: Sie‘ re stark empfohlen, PDO zu verwenden, wie mysql_* Funktionen werden auslaufen. Sie können all diese addslashes() auch loswerden!


Für den Einsatz, können Sie wie folgt vorgehen:

Halten in Sitzung einige Informationen über das CSV

$import = array(
    'current' => 0, 
    'total' => 0, // Estimated 
    'begun' => 0, 
    'fpos' => 0, 
    'flen' => 0, // Total CSV file size 
    'errors' => 0, 
); 

und erstellen Sie einen eindeutigen Index für die Themen, für die Sie keine Duplikate (CREATE UNIQUE INDEX ...)

Wenn Sie aus der CSV importieren:

- open $csv file 
- fseek() the file to the $session['fpos'] offset 
- MySQL set AUTOCOMMIT to off; 
- MySQL BEGIN WORK; 
- Get current time plus 10 seconds into $ttl 
- loop 
    - read one record using, say, fgetcsv() 
    - try 
     - insert into the DB using INSERT IGNORE 
    - catch PDO error 
     - MySQL ROLLBACK, $session['errors']++ and immediately die(). 
    - is time() equal or above $ttl? If so, break 
- update the session object, set its 'errors' to 0, put fpos() of $csv file into it 
- MySQL COMMIT; 
- Your ETA is $session['begun'] + (time()-$session['begun'])*($session['fpos']/$session['flen']). 

Mit der obigen Methode dauert es etwas mehr als 10 Sekunden für jede Iteration.

Wenn die Einfügungen gut verlaufen, enthält die neue Sitzung den nächsten Dateioffset, von dem aus gestartet werden soll.

Wenn ein Fehler auftritt, wird der gesamte Transaktionsblock zurückgesetzt, und es wird so aussehen, als würde es nie gestartet. Sie verfolgen aufeinanderfolgende Fehler (sie könnten bedeuten, dass etwas in der CSV falsch ist).

Sie können dies tun und das Sitzungsobjekt als JSON zurückgeben. Dann können Sie die CSV-Datei, die das obige Skript aufruft, z. B. mit jQuery $.get() importieren und damit eine Fortschrittsanzeige aktualisieren. Sie werden in der Lage, die voraussichtliche Ankunftszeit für das gesamte Verfahren zu berechnen:

importing [##############     ] 48%, 32m 15s left 

Das bedeutet, dass die „UPLOAD“ Seite muss die CSV-Datei in einem temporären Verzeichnis verschieben und sofort die HTML-Anzeige, die den Fortschritt zeigen Bar. Dann ist dieser HTML (und Javascript) dafür verantwortlich, dass der Upload fortgesetzt wird.

Es gibt auch Upload-Bibliotheken wie PLupload, die die Datei in "Chunks" hochladen und einen eigenen Fortschrittsbalken anzeigen. Da in der Regel Netzwerk-Upload langsamer als MySQL-Upload ist, ist es sehr bequem, die Chunks einzeln zu laden. Der letzte CSV-Datensatz in jedem Chunk wird wahrscheinlich abgeschnitten, so dass irgendeine Art von Überprüfung erforderlich ist, und das "Fragment" dieses Chunks muss gespeichert und an den nächsten Chunk angehängt werden, um den Datensatz zu rekonstruieren.

Die plupload-Methode hat den Vorteil, dass der MySQL-Import scheinbar keine Zeit benötigt - sobald der Upload abgeschlossen ist, sind die Daten selbst bei sehr großen Dateien verfügbar. Sie legen es in eine Tabelle mit einem temporären Namen (nicht eine temporäre MySQL-Tabelle oder Sie riskieren Datenverlust), und wenn der Upload abgeschlossen ist, benennen Sie einfach die Tabelle automatisch um.

Verwandte Themen