I'm trying to import a .csv file in a MySQL database using HTML/PHP. The code is:
HTML
<form method="post" action="" enctype="multipart/form-data">
File: <input type="file" name="csv">
<input type="submit" value="Send" name="subCSV">
</form>
PHP
$file = $_FILES["csv"]["tmp_name"];
try {
$query = $connexion -> prepare("LOAD DATA INFILE ? into TABLE myTable FIELDS TERMINATED BY ';' LINES TERMINATED BY '\\r\\n' IGNORE 1 ROWS");
$query->bindValue(1, $file, PDO::PARAM_STR);
$query->execute();
} catch(PDOException $e) { echo $e->getMessage(); $errorCode = $e->getCode();
But I'm getting that error:
File '/tmp/phpl8eY59' not found (Errcode: 13)
Specifying the file explicitly works. The permissions are fine, the user running Apache and the file owner are identical. I have granted file permission on the database user.
Apparently configuring AppArmor would solve the problem, but I'm not using it, as it is not installed on my server.
You could try using "LOAD DATA LOCAL INFILE". See eg the answer here: LOAD DATA INFILE does not work. The problem is that there seem to be various causes of this problem.
I've solved the problem with this:
chmod($file, 0644);
The Apache/PHP user and the MySQL user were not the same.
Related
I'm uploading a csv file to my php server with this form:
<form action="importCSV.php" method="post" enctype="multipart/form-data">
<br>Select file: <input type="file" name="file">
<br><input type="submit" name="import" value="Import file">
</form>
And what I want to do with that file is to add its content to a table in my mysql server.
$url=$_FILES['file']['tmp_name'];
$con = new mysqli(HOST, US, PW, BBDD);
$sql="load data local infile '" . $url. " into table users fields terminated by ':'";
$con->query($sql);
$con->close();
The problem is that in the "tmp" folder of the php server doesn't appear the csv file, but in this line $url=$_FILES['file']['tmp_name'] $url has a real url with a tmp_name. I don't understand what's happening there: I have the url with the tmp_name of the file but it actually doesn't exists?
I have checked the php.ini file and this are the values for the file uploads:
file_uploads=On
upload_tmp_dir="C:\xampp\tmp"
upload_max_filesize=2M
max_file_uploads=20
I'm not worried about the "upload_max_filesize", the file I'm trying to upload has a size of only 56 bytes.
Please, any ideas?
I can't believe this...
It seems that the mysql server doesn't understand this character \. It's only a problem of compatibility between operative systems.
The solution is only to replace the character: $url= str_replace("\\", "/", $url).
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.
On trying following code to read a database from a server (through localhost on the desktop itself). The database file opens for reading but not for inserting records.
FORM HTML FILE:
<html>
<form action="fruit_action.php" method="post">
<p>Enter name of fruit: <input type="text" name="sent_fruit" /></p>
<p><input type="submit" /></p>
</form>
</html>
ACTION PHP FILE:
<html>
<?php
$fruit = $_POST['sent_fruit'] ;
echo "<p>$fruit</p>" ;
$db = new SQLite3("/home/iusr/fruit_prefs.sqlite") or die('Not able to open file.');
# PRINT OUT ITEMS IN DATABASE CORRECTLY:
$res = $db->query("select * from fruit_codes");
echo "<p>Fruits in database:";
while ($row = $res->fetchArray()) { echo "$row[name_fruit];"; }
echo "</p>";
# ABOVE WORKS WELL;
# ERROR ON FOLLOWING LINE:
$result = $db->exec('INSERT INTO fruit_codes (name_fruit) VALUES ($fruit); ') or die('Not able to insert record');
$db = null;
?>
</html>
OUTPUT:
mango
Fruits in database:apple;pear;orange;
Warning: SQLite3::exec(): unable to open database file in /var/www/htdocs/fruit_action.php on line 15
Not able to insert record
I am working in Linux. The database file is in home directory and all permissions are on:
$ ls -l fruit*.sqlite
-rwxrwxrwx 1 iusr users 7168 Jun 9 19:15 fruit_prefs.sqlite
How can I sort out this error? Thanks for your help.
PHP(webserver user) creates some files ( journals ) to execute SQLite3::exec(), and so it needs write permission on your database.
Try giving write permission to PHP( webserver user ) on that db file.
More info http://php.net/manual/en/sqlite3.exec.php, see User Contributed Notes.
Also https://www.daniweb.com/programming/web-development/threads/462894/unable-to-open-db-file
I assume, PHP needs to be able to write the directory where the SQLite DB file is located, e.g. for journaling, which seems not to be the case in your example. Try locating the DB in the applications docroot.
I have found many "partial" answers to questions similar to this, but I'm new to PHP and MySQL and there doesn't seem to be one nice big coherent answer out there; What I'm trying to do is this:
Get all the data from a MySQL table called "producers".
Have the user select a filename/'save as' location on their local machine.
PHP / MySQL / HTML gets the data and writes to it as a CSV file.
Parts 1 and 3 are easy; but getting a way for the user to select a file location/filename seems to be nigh on impossible. It's simple in HTML for a user to select a file for upload, so why is it so hard for me to find a way for a user to select a "save" location/name? Surely this is not a security risk - downloading from a server is far less of a security risk than uploading something to a server.
I'd like to be able to use the nice and simple MySQL method, but I don't know how to just send this command from PHP to MySQL; just putting it in a mysqli_query doesn't seem to do anything:
SELECT prodCompany,prodPhone,prodFirstname FROM producers
INTO OUTFILE '/Users/me/Desktop/file.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
(this method works fine from within phpMyAdmin).
So I've gone for the clunky step by step PHP method for now, which works, but obviously only ever saves "file.csv" to my desktop. I have read the odd mention of MIME types, but I'm not sure how this could help me and how to implement it.
All I want is to trigger a file selector dialog box, to get that filepath/name into the $filename variable. But after a couple of days of frustration, I cannot find anything that works. Any help or suggestions would be greatly appreciated!
Paul
The PHP that saves to that one file:
<?php
// Create connection
$con=mysqli_connect("xxxxxxxxx","xxxxxxxxx","xxxxxxxxxxxxxx","xxxxxxxxxx");
// Check connection
if (mysqli_connect_errno())
{ echo "Failed to connect to MySQL: " . mysqli_connect_error(); }
$filename = '/Users/me/Desktop/file.csv';
$headers = array('prodCompany', 'prodPhone', 'prodFirstname');
$handle = fopen($filename, 'w');
fputcsv($handle, $headers, ',', '"');
$sql = mysqli_query($con, 'SELECT * FROM producers');
while($results = mysqli_fetch_array($sql)) {
$row = array(
$results['prodCompany'],
$results['prodPhone'],
$results['prodFirstname']
);
fputcsv($handle, $row, ',', '"');
}
fclose($handle);
?>
Okay, the concept being you want to generate a csv and have the user save it.
Form to get file name
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Example</title>
</head>
<body>
<form name="test" action="csv_gen.php" method="post">
<label for="filename">File name </label>
<input type="text" name="filename" id="filename" />
<input type="submit" name="submit" value="go get file" />
</form>
</body>
</html>
Script to process and force csv download
<?php
if($_POST) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='.$_POST['filename'].'.csv');
//replace this with whatever generates your csv and print it
echo "field1,field2,field3,field4,field5\n";
}
?>
This will do the force download. With newer browsers that have a default download location, such as Chrome, this will download the file immediately using whatever file name a user enters into the form field. They would then open that location and move the file. That is pretty standard browser functionality that I wouldn't try to overwrite. It might confuse people that have a default location set for downloads.
Hopefully that helps get you started.
I recently ran into a similar problem in a one file php app where all forms submit to the same index.php. After submitting the form, I did the following:
Re-fetched the database results
Used fopen to create a file called 'out.csv' somewhere on the server
Wrote each row of the result set to out.csv
Redirected to out.csv with: header("Location: relative_path_to_csv/out.csv");
The default save dialog appears the same way it would if you were to make a link to the file and click on it.
The drawback is that if it's called concurrently by multiple users, that same 'out.csv' would be overwritten by others. The solution to that is to use a unique identifier for the file name and have some process to periodically clean out the csv directory (cron job).
I'm trying to create a script where a user can upload a csv file into a table. I got the tutorial from shotdev.com, I'm getting the following errors, what am I doing wrong?
**The following command is not allowed: copy
The following command is not allowed: fopen**
Page1.php
<form action="page2.php" method="post" enctype="multipart/form-data" name="form1">
<input name="fileCSV" type="file" id="fileCSV">
<input name="btnSubmit" type="submit" id="btnSubmit" value="Submit">
</form>
Page2.php
<?
copy($_FILES["fileCSV"]["tmp_name"],"shotdev/".$_FILES["fileCSV"]["name"]); // Copy/Upload CSV
include 'datalogin.php';
$objCSV = fopen("shotdev/".$_FILES["fileCSV"]["name"], "r");
while (($objArr = fgetcsv($objCSV, 1000, ",")) !== FALSE) {
$strSQL = "INSERT INTO customer ";
$strSQL .="(CustomerID,Name,Email,CountryCode,Budget,Used) ";
$strSQL .="VALUES ";
$strSQL .="('".$objArr[0]."','".$objArr[1]."','".$objArr[2]."' ";
$strSQL .=",'".$objArr[3]."','".$objArr[4]."','".$objArr[5]."') ";
$objQuery = mysql_query($strSQL);
}
fclose($objCSV);
echo "Import completed.";
?>
It looks like you're running PHP in safe mode or with certain functions disabled. For security reasons web hosts often disable file commands.
You could discuss your requirements with your web host - some are flexible enough to enable the functions for you if you ask nicely.
Otherwise you'll have to achieve it without using the disabled file commands. One way would be to create a textarea in an HTML form in which you paste the CSV. SUbmit it to your PHP script which then runs the MySQL import.
Hope that helps
This seems to be a limitation imposed by the hosting provider (they seem to have put fopen() and copy() on the list of disabled functions, which is rather silly), in which case you probably can't do anything about it except ask the provider to relax the restriction.
Generally though, you're not handling the uploaded files properly using move_uploaded_file(). Use it as shown in the example in the manual link.