How do I load a text file to Database in PHP? - php

Originally $filepath is like this
$filepath=$_SERVER['DOCUMENT_ROOT']."/".SCRIPTFOLDER."somefile.txt";
$sqlquerynew = "LOAD DATA INFILE '".$filepath."' INTO TABLE mytable FIELDS TERMINATED BY ','";
mysql_query($sqlquery);
That works. It sits on the server.
But what if I want to put somefile.txt outside the same server? If I put that in dropbox, and reuse the code like the following, it doesn't do anything.
$sqlquerycreate = / ** Here insert DB scheme code **/
$filepath="http://example.com/somefile.txt";
$sqlquerynew = "LOAD DATA INFILE '".$filepath."' INTO TABLE mytable FIELDS TERMINATED BY ','";
mysql_query($sqlquery);
What should I do instead? The text file contains the data for the table.
Thanks.
$data_file = file_get_contents('http://dl.dropbox.com/u/14655573/john/nyccrash.txt');
file_put_contents('C:\xampp\htdocs\import\nyccrash.txt', $data_file);
$filepath = "C:\xampp\htdocs\import\nyccrash.txt";
echo $filepath;
$sqlquery = "LOAD DATA INFILE '".$filepath."' INTO TABLE nyccrash FIELDS TERMINATED BY ',' (crash_year, accident_type, collision_type,weather_condition,light_condition,x_coordinate,y_coordinate)";
Okay. I see this file now. But it didn't get import to the DB. This is XAMPP. But I will, eventually, move to Ubuntu. What's the problem with this code?

Try this:
$file = file_get_contents("http://example.com/somefile.txt");
$filepath=$_SERVER['DOCUMENT_ROOT']."/".SCRIPTFOLDER."somefile.txt";
file_put_contents($filepath, $file);
$sqlquerycreate = / ** Here insert DB scheme code **/
$sqlquerynew = "LOAD DATA INFILE '".$filepath."' INTO TABLE mytable FIELDS TERMINATED BY ','";
mysql_query($sqlquery);
Hope it helps..

The LOAD DATA INFILE reads a file from the client or from the server, not from the internet.
You could use copy() to first download the file to a temporary directory, and then point LOAD DATA INFILE to that directory.

Create first a temporary file on your server:
$tmpFile = tempnam('my-tmp-dir', 'TMP');
$ok = copy('http://example.com/somefile.txt', $tmpFile);
if ( !$ok ) exit('ERROR!');
// Then use $filepath in your SQL query
$sqlquerynew = "LOAD DATA INFILE '".$filepath."' INTO TABLE mytable FIELDS TERMINATED BY ','";
mysql_query($sqlquery);
unlink($tmpFile);

You can first import data in local file with
//read data from remote file
$data_file = file_get_contents($http_url);
// put data in a local file
$temp_file = tempnam(sys_get_temp_dir(),'TMP');
file_put_contents($temp_file,$data_file);
//now use $temp_file into the SQL query
....
//Delete temp file
unlink($temp_file);
Please note that PHP has functions to get the system's TEMP path, and to generate a temporary filename.
In the /tmp you should not have permissions issues.

Related

Load Data Infile Not Insert Data to phpMyAdmin

I tried to change from insert to to load data infile for uploading a large CSV file.
I explored some examples on how to use load data infile. But it's not working and giving this Error:
SQLSTATE[HY000]: General error: 29 File '/direct1/#tmp/phpFZLLYA' not found (Errcode: 13 "Permission denied").
This is my code:
$target_dir = '/direct1/#tmp/';
$target_file = $target_dir . basename($_FILES["file"]["tmp_name"]);
$stmt = $dbcon->prepare("LOAD DATA INFILE '$target_file' INTO TABLE Rain FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n' IGNORE 1 LINES(id, date, vol, day)");
$stmt->execute();
When I try to change to load data local infile based on related discussion, error code does not appear but the data is not inserted to the database. I am using INNODB storage engine.
I solved the error by using move_uploaded_file function and the file can be access.

how to copy mysql DB from localhost to server using php?

I have a php project running in my local machine(angular,php,mysql).Same copy of project running in online.
My Aim is to Sync(copy local db to server db) every one hour by running any PHP Script using angular 'set Interval' function.
What is the IDEA behind this functionality should i use?
or how i will achieve this ?
Any suggestions will be great help for me,
and Thanks in advance.
If your database tables not gonna change what you can do is create a function select all the data from your local database and pass that data to online function to update your online database with new or updated records.
For ex:
If you have a table called users. From AJAX you will select all local data and create JSON Object pass the data to script function.
From that JSON Object you will pass data to online php file and update your online database from it.
Note: You have to careful with giving lot of conditions to check whether data get missing or override.
You'll have to write a service and some code to dump your database (if you want to sync complete database every time) follow this answer
After dumping your sql next you have to upload the file to your server via the service. Upon receiving you can load the data again mysql -u username -p database_name < file.sql
However I won't recommend this, try exploring database approach of Master-Slave Database, where your local server's database will be a Master and your remote server will be slave. Your data will automatically be synchronized.Please see this tutorial
You can implement interface to select tables you want to import in live. Use below code generate CSV files of selected tables and prepare array.
<?php
$file_name_flat = 'TABLE-NAME.csv'; // Replace TABLE-NAME with your selected table name.
$fpointer = fopen(FOLDER-LOCATION.$file_name_flat, 'w+'); // Open CSV file. Replace
FOLDER-LOCATION with your local folder path where you want to save this CSV files.
//Execute query to get all columns data
$query = "select * FROM TABLE-NAME WHERE 1"; // Replace TABLE-NAME with your selected
table name. You can set other conditions based on your requirement.
//Execute query as per your CMS / Framework coding standards and write CSV file.
$result_flat = $DB_Connection->query($query)->fetchAll('assoc');
foreach ($result_flat as $fields) {
fputcsv($fpointer, $fields);
}
//Prepare Array of CSVs to create ZIP file
$files = array($file_name_flat);
fclose($fpointer); // close CSV file after successfully write.
?>
CREATE ZIP of CSVs
//Create ZIP
$zipname = 'tables_'.date('Y-m-d-H-i-s').'.zip';
createZipFile($files,$zipname,FOLDER_LOCATION); //Replace FOLDER-LOCATION with your
local folder path where you saved CSV files.
/* createZipFile Funcation to create zip file Both params are mandatory */
function createZipFile($files_names = array(),$zipfileName, $files_path=""){
$zip = new \ZipArchive;
$zip->open(TMP.$zipfileName, \ZipArchive::CREATE);
foreach ($files_names as $file) {
$zip->addFile($files_path.$file,$file);
}
$zip->close();
foreach ($files_names as $file) {
unlink($files_path.$file);
}
///Then download the zipped file.
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipfileName);
header('Content-Length: ' . filesize(FOLDER_LOCATION.$zipfileName));
readfile(TMP.$zipfileName);
unlink(TMP.$zipfileName);
die;
}
Now Implement a form to upload this zip file on live server. In Post action of this form add code to get zip file.
$filename = $_FILES['filename']['name'];
$source = $_FILES["filename"]["tmp_name"];
//Upload zip file to server location. Replace SERVER_FOLDER_PATH to server's location
where you want to save uploaded zip.
if(move_uploaded_file($source, SERVER_FOLDER_PATH)) {
//Extract ZIP file
$zip = new \ZipArchive();
$x = $zip->open($target_path);
if($x === true) {
$zip->extractTo(PATH_TO_SAVE_EXTRACTED_ZIP); // change this to the correct site path
$zip->close();
$cdir = scandir(PATH_TO_SAVE_EXTRACTED_ZIP); // Read DIR
$fieldSeparator = ",";
$lineSeparator = '\n';
foreach ($cdir as $key => $value)
{
if (!in_array($value,array(".","..")))
{
$fileName = PATH_TO_SAVE_EXTRACTED_ZIP.$value; // replace
PATH_TO_SAVE_EXTRACTED_ZIP with your server path
$tableName = SET_TABLE_NAME; // You have to set the logic to get the table name.
if (is_file($fileName))
{
// User MYSQL "LOAD DATA LOCAL INFILE" to IMPORT CSVs into particular tables. There are option available for this LOAD DATA process. It will import your CSV to particular table. No need to execute loop to insert data one by one.
$q = 'LOAD DATA LOCAL INFILE "'.$fileName.'" REPLACE INTO TABLE '.$tableName.' FIELDS TERMINATED BY "' .$fieldSeparator. '" Enclosed BY '.'\'"\''.' LINES TERMINATED BY "'.$lineSeparator.'"';
$DB_Connection->query($q);
}
}
}
}
You can check LOAD DATA of MySQL from - MYSQL
You can run a cron job on your local computer that exports the MySQL data using mysqldump and then uploads it to the server using rsync and sshpass.

Load data in file from form upload

I'm trying to insert data into MySQL table using the load data infile query. I have an HTML form that accepts a text file for upload, and then tries to process.
File
00|Oakleaf Forest|Norfolk|VA|United States|PC
01|Igo|Lowell|MA|United States|PC
02|Mint|Lawrence|MA|United States|PC
03|Hosa|Boston|MA|United States|PC
HTML
<p>Please upload file below:</p>
<form action="process.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" accept="text/plain">
<input type="submit">
</form>
PHP
/* processFile
* Process the submitted file
*
* #param Array - file for processing
*/
function processFile($file) {
// Get global variable
global $DB;
// file contents
$file_contents = $file["tmp_name"];
$SQL_statement = "LOAD DATA INFILE '$file_contents' INTO TABLE organization FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n' IGNORE 2 LINES
(ein, legal_name, city_name, state_name, country_name, description);";
// Run SQL query
$DB->execute($SQL_statement);
}
When I upload the file, nothing is inserted into the table.
I've tried debugging with echo($SQL_statement);, which returns the following query:
LOAD DATA INFILE '/Applications/XAMPP/xamppfiles/temp/phpOtL2q1' INTO TABLE organization FIELDS TERMINATED BY '|' LINES TERMINATED BY ' ' IGNORE 2 LINES (ein, legal_name, city_name, state_name, country_name, description);
What am I missing here?
LOAD DATA INFILE requires that the file be readable by the database process. I doubt that the temporary upload file is world-readable, it's probably only readable by the webserver userid.
One thing you can try is changing the permissions on the temp file first:
chmod($file["tmp_name"], 0444);
However, this still might not work if the directory containing the temp files is not world-readable. Another solution is to use LOAD DATA LOCAL INFILE. This reads the file in PHP, not the database server, so any file that the PHP process can read can be loaded. It's not as efficient, since all the file data has to be sent over the database connection, but it avoids permission problems.
So try the first method first, if it doesn't work try the second.

PHP. Transferring downloaded csv to mysql database - how can I store downloaded csv file in php memory

I would like to store data downloaded from a website into my mysql database.
I use my function "CallAPI("GET", $url, $data = false)" to access the database using a url such as "http://www.xflow1.com/xGlobalHist.csv/"...
So my call $results = CallAPI($method, $url, $data = false); returns a comma delimted array that is saved in the variable "$results". I can echo $results in a web page and it show me the data, all comma delimited. All good `til here.
To upload the csv to my mysql database I want to use the "LOAD DATA INFILE" function as so:
$upload = <<<eof
LOAD DATA INFILE $results
INTO TABLE X_Adjusted_All
FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(Cusip, Date, Price)
eof;
The snag arises as "LOAD DATA INFILE $results" does not work as LOAD DATA INFILE only wants a filename, so I would like to store $results as a csv file in the memory to avoid creating and deleting files all the time. I thought this may work:
$fp = fopen('php://memory', 'w');
fputcsv($fp, $results);
Alas no. Does anyone have any idea how to take the downloaded csv file and save it to the phps memory as a csv file for use in the LOAD DATA INFILE function?
MySQL cannot read directly from PHP's memory. You need to create an external file using tempnam(). That file can then be read by MySQL. You could also create a temporary file and find out the filename as mentioned in this question.
The example of tempnam() shows how to write to that file:
<?php
$tmpfname = tempnam("/tmp", "FOO");
$handle = fopen($tmpfname, "w");
fwrite($handle, $results);
fclose($handle);
// do something
unlink($tmpfname);
This will store the contents of $results to a file called $tmpfname which you can store in mysql using LOAD DATA INFILE $tmpfname.
As mentioned in the comments, you could create a ram drive to store that file, if performance is an issue.

Upload CSV file and import it to database using Laravel

I have this method that uploads a file of a CSV format, but now i want to know how to upload it into columns in my database.
My method:
public function postUpload ()
{
if (Input::hasFile('file')){
$file = Input::file('file');
$name = time() . '-' . $file->getClientOriginalName();
// Moves file to folder on server
$file->move(public_path() . '/uploads/CSV', $name);
return 'Ok'; // return for testing
}
}
So my question would be within this method how can i can put it into the database ?
this one should work for you, it uses PDO + mySql's "LOAD DATA" approach
private function _import_csv($path, $filename)
{
$csv = $path . $filename;
//ofcourse you have to modify that with proper table and field names
$query = sprintf("LOAD DATA local INFILE '%s' INTO TABLE your_table FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\"' LINES TERMINATED BY '\\n' IGNORE 0 LINES (`filed_one`, `field_two`, `field_three`)", addslashes($csv));
return DB::connection()->getpdo()->exec($query);
}
So combined with your code, it could be something like the below
public function postUpload ()
{
if (Input::hasFile('file')){
$file = Input::file('file');
$name = time() . '-' . $file->getClientOriginalName();
//check out the edit content on bottom of my answer for details on $storage
$storage = '/some/world/readible/dir';
$path = $storage . '/uploads/CSV';
// Moves file to folder on server
$file->move($path, $name);
// Import the moved file to DB and return OK if there were rows affected
return ( $this->_import_csv($path, $name) ? 'OK' : 'No rows affected' );
}
}
EDIT
One thing to be noted, as per the error you report in comments which is probably some permissions issue (OS error code 13: Permission denied)
Please see: http://dev.mysql.com/doc/refman/5.1/en/load-data.html
"For security reasons, when reading text files located on the server,
the files must either reside in the database directory or be readable
by all. Also, to use LOAD DATA INFILE on server files, you must have
the FILE privilege. See Section 5.7.3, “Privileges Provided by
MySQL”."
As reported on mySql bug tracker (http://bugs.mysql.com/bug.php?id=31670) it seems that you need particular permission for all the folders in the csv file path:
All parent directories of the infile need world-readable I think
aswell as just the directory and infile...
So for an infile here: /tmp/imports/site1/data.file
you would need (I think, 755 worked) r+x for 'other' on these
directories: /tmp /tmp/imports
as well as the main two: /tmp/imports/site1
/tmp/imports/site1/data.file
To sum up:
To solve the "sqlstate hy000 general error 13 can't get stat of..." issue you have to move the uploaded file to a location with proper permissions (so not neccessarily the current one you are using) try something like "/tmp/import".
While load data infile is the quickest way, I prefer to use a lib like https://github.com/ddeboer/data-import or https://github.com/goodby/csv for 2 reasons.
It is extensible, what if your data source changes to excel files or a mongo db or some other method?
It is mallable, if you need to convert dates, or strings or numbers you can do it conditionally which cannot be done with a batch command.
my 2c

Categories