i know some of you are going to say that this isnt the correct way but im on a tight deadline to finish an application and as of now i cant go back and modify the code to store the images in a directory.
now that thats cleared
the question i had is i inserted an image into the database by typing this.
(dont mind the class security call, all that is doing is a few checks if the data is valid)
$filename = $security->secure($_FILES['imgschool']['name']);
$tmpname = $security->secure($_FILES['imgschool']['tmp_name']);
$imgsize = $security->secure($_FILES['imgschool']['size']);
$imgtype = $security->secure($_FILES['imgschool']['type']);
$school = $security->secure($_POST['school']);
//begin upload
if($imgsize > 0) {
$handle = fopen($tmpname, "r");
$content = fread($handle, filesize($tmpname));
$content = addslashes($content);
//code to add all this to database
}
the variable $content is the image and all its getting is the addslashes. i remember someone once mentioning to do it with something called base64 but i can barely recall how it was written.
this is how i am calling the image from the database
aside from all the queries and whatnot
this is the main part that is calling the image
header("Content-length: ".$imgsize);
header("Content-type: ".$imgtype);
header("Content-Disposition: attachment; filename=".$imgname);
print $row['img'];
the problem i am having is that instead of the image showing. the url is only showing, so in this case i only see this
http://localhost/admin/school-catalog.php?page=gallery&id=4
when opening the page to view the image with the correct params set in the url.
for those that wanted to see the query that is being done to save the image and so forth
i copied the whole section
//save image to db
if(isset($_POST['btnupload'])) {
$filename = $security->secure($_FILES['imgschool']['name']);
$tmpname = $security->secure($_FILES['imgschool']['tmp_name']);
$imgsize = $security->secure($_FILES['imgschool']['size']);
$imgtype = $security->secure($_FILES['imgschool']['type']);
$school = $security->secure($_POST['school']);
//begin upload
if($imgsize > 0) {
$handle = fopen($tmpname, "r");
$content = fread($handle, filesize($tmpname));
$content = base64_encode($content);
}
$save = mysql_query("insert into tbl_schoolgallery(id,hash,img,imgtype,imgsize) values(null,'$school','$content','$imgtype','$imgsize')") or die(mysql_error());
header("Location: school-catalog.php?page=school_gallery");
}
//call image from db
$query = mysql_query("select * from $tbl where id = '$id'") or die(mysql_error());
while($row = mysql_fetch_assoc($query)) {
$imgtypeget = explode("/", $row['imgtype']);
$imgname = "img.".$imgtypeget[1];
$imgtype = $row['imgtype'];
$imgsize = $row['imgsize'];
header("Content-length: ".$imgsize);
header("Content-type: ".$imgtype);
print base64_decode($row['img']);
print $row['img'];
}
Using addslashes is extremely incorrect. Depending on whether your column is a TEXT field or a BLOB field, you should use Base64 or mysql_real_escape_string.
Using Base64 isn't that hard; you may as well use that way. Just replace addslashes with base64_encode and echo the image with base64_decode.
There's a bit easier way to write the whole thing, for that matter:
// begin upload
if ($imgsize > 0)
{
$content = file_get_content($tmpname);
$content = base64_encode($content);
}
And then to output you really only need to do
header("Content-type: ".$imgtype);
echo base64_decode($img);
If the column is a BLOB, however, you can directly use mysql_real_escape_string:
// begin upload
if ($imgsize > 0)
{
$content = file_get_content($tmpname);
$content = mysql_real_escape_string($content);
}
And then:
header("Content-type: ".$imgtype);
echo $img;
Although judging from your current symptoms, I'm guessing you also have a bug relating to how your image is being stored and recalled from the database, and I'd need to see that part of the code where you make the queries to insert and read from the database before I could help you fix that part.
Your current code seems mostly fine. A few issues:
print base64_decode($row['img']);
print $row['img'];
You probably meant to get rid of the second row. Also, you should use echo instead of print; everyone uses it, it can be slighty faster sometimes, and print doesn't really have any benefit other than returning a value:
echo base64_decode($row['img']);
$security->secure() appears to be some sort of sanitization function. Just use mysql_real_escape_string() - that's the one you're supposed to use. Except $imgsize; you might want to use intval() on that one since you know it's supposed to be an integer.
Also here:
$query = mysql_query("select * from $tbl where id = '$id'") or die(mysql_error());
You name the table tbl_schoolgallery a few rows above that. I assume $tbl == 'tbl_schoolgallery', but for consistency, you should either use $tbl in both places or tbl_schoolgallery in both places.
Also, replace that while with an if - your code would cause trouble if it ever loops more than once, anyway.
Related
I try to show an image stored in a database. I wrote it with
$image = file_get_contents($testPfad);
$dateigroesse = filesize($testPfad);
$arrData = unpack("H*hex", $image);
$data_string = "0x".$arrData['hex'];
$sql = "INSERT INTO EHS.dbo.T_Signaturen (UnterschriftsDateiName,UnterschriftsBild,Dateigroesse,terminID) VALUES (
'".$unterschriftsFileName."',
CONVERT(varbinary(max),'$data_string'),
'".$dateigroesse."',
'384_234')";
echo '<hr>'.$sql;
insert($sql);
With this code I output the image.
header("Content-type: image/jpeg");
$query = "SELECT Dateigroesse, CONVERT(varchar(max), UnterschriftsBild) as content_data FROM EHS.dbo.T_Signaturen WHERE ID = '10'";
$result = query($query);
$content = $result[1]["content_data"];
$filesize = $result[1]["Dateigroesse"];
$content = substr ($content, 2); // entfernt 0x
$content = pack("H*", $content);
print $content;
Everything works fine but only a part of the image is shown. I reduced the image size from 20kb to 2kb and much more is shown so I think ANYWHERE the binary data is cut. The Database Column is a varbinary(max)
Please let us not discuss wether it is rational to store blob in databases :) :)
The solution was to increase the max accepted string length of odbc in php.ini. It was set to 4069 chars
did you try to define your column as BLOB (up to 2 GB)?
are you sure, that the complete image is stored (maybe that function is wrong)
I am simply generating a csv file based on data stored in a mysql table. The generated csv, when opened in excel, seems mostly ok, but whenever it has a newline character, excel puts the data on a new row. Any idea how to prevent that?
Sample data
line 1 some data
another data
CSV generation code:
header("Content-Type: text/csv; charset=UTF-8");
header("Content-Disposition: attachment; filename=\"".$MyFileName."\"");
$filename = $MyFileName;
$handle = fopen("temp_files/".$filename, "r");
$contents = fread($handle, filesize("temp_files/".$filename));
fclose($handle);
echo $contents;
exit;
content snippet I used to get rid of new line(didn't work):
$pack_inst = str_replace(',',' ',$get_data->fields['pack_instruction']);
$pack_inst = str_replace('\n',' ',$pack_inst);
$pack_inst = str_replace('\r',' ',$pack_inst);
$pack_inst = str_replace('\r\n',' ',$pack_inst);
$pack_inst = str_replace('<br>',' ',$pack_inst);
$pack_inst = str_replace('<br/>',' ',$pack_inst);
$pack_inst = str_replace(PHP_EOL, '', $pack_inst);
$pattern = '(?:[ \t\n\r\x0B\x00\x{A0}\x{AD}\x{2000}-\x{200F}\x{201F}\x{202F}\x{3000}\x{FEFF}]| |<br\s*\/?>)+';
$pack_inst = preg_replace('/^' . $pattern . '|' . $pattern . '$/u', ' ', $pack_inst);
$content .=','.$pack_inst;
According to RFC 4180, if a column's content contains the row delimiter (\r\n), the column delimiter (,) or the string delimiter (") then you must enclose the content inside double quotes ". When you do that, you must escape all " characters inside the content by preceding them with another ". So the following CSV content:
1: OK,2: this "might" work but not recommended,"3: new
line","4: comma, and text","5: new
line and ""double"" double quotes"
1: Line 2
Will produce 2 rows of CSV data, first one containing 5 columns.
Having said that, have a look at fputcsv() function. It will handle most gory details for you.
What you show is not the CSV generation code, it is simply the code that you have used to force a download to the browser. Regardless, the function that you need to sort this out is fputcsv(), which will automatically consider all sorts of edge cases that any code you write to convert tabular data to CSV format will likely not consider.
You say you are basing this on data in MySQL table, here is a basic framework for creating the CSV file, assuming the MySQLi extension used in a procedural manner:
<?php
// Connect to database and generate file name here
$fileName = 'file.csv';
// Get the data from the database
$query = "
SELECT *
FROM table_name
WHERE some_column = 'Some Value'
ORDER BY column_name
";
if (!$result = mysqli_query($db, $query)) {
// The query failed
// You may want to handle this with a more meaningful error message
header('HTTP/1.1 500 Internal Server Error');
exit;
} else if (!mysqli_num_rows($result)) {
// The query returned no results
// You may want to handle this with a more meaningful error message
header('HTTP/1.1 404 Not Found');
exit;
}
// Create a temporary file pointer for storing the CSV file
$tmpFP = fopen('php://temp', 'w+');
// We'll keep track of how much data we write to the file
$fileLength = 0;
// Create a column head row and write first row to file
$firstRow = mysqli_fetch_assoc($result);
$fileLength += fputcsv($tmpFP, array_keys($firstRow));
$fileLength += fputcsv($tmpFP, array_values($firstRow));
// Write the rest of the rows to the file
while ($row = mysqli_fetch_row($result)) {
$fileLength += fputcsv($tmpFP, $row);
}
// Send the download headers
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="'.$fileName.'"');
header('Content-Length: '.$fileLength);
// Free some unnecessary memory we are using
// The data might take a while to transfer to the client
mysqli_free_result($result);
unset($query, $result, $firstRow, $row, $fileName, $fileLength);
// Prevent timeouts on slow networks/large files
set_time_limit(0);
// Place the file pointer back at the beginning
rewind(tmpFP);
// Serve the file download
fpassthru($tmpFP);
// Close the file pointer
fclose($tmpFP);
// ...and we're done
exit;
I have a database set up which accepts user registrations and their details etc. I'm looking to export the database to an excel file using php.
The problem I am having is that some of the entrants have entered foreign characters in, such as Turkish, which has been written into the database 'incorrectly' - as far as I have ascertained, the charset was likely set up incorrectly when it was first made.
I have made my code to export the database into excel (below) but I cannot get the Excel document to show correctly regardless of how I try to encode the data
<?php
require_once('../php/db.php');
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=Download.xls");
header("Pragma: no-cache");
header("Expires: 0");
$query = "SELECT * FROM users";
$result = mysqli_query($link, $query);
if($result) {
$count = mysqli_num_rows($result);
for($i=0; $i<$count; $i++) {
$field = mysqli_fetch_field($result);
$header .= $field->name."\t";
while($row = mysqli_fetch_row($result)) {
$line = '';
foreach($row as $value) {
if((!isset($value)) OR ($value == "")) {
$value = "\t";
} else {
$value = str_replace('"', '""', $value);
$value = '"'.$value.'"'."\t";
}
$line .= $value;
}
$data .= trim($line)."\n";
}
$data = str_replace("\r", "", $data);
if($data == "") {
$data = "\n(0) Records Found!\n";
}
}
print mb_convert_encoding("$header\n$data", 'UTF-16LE', 'UTF-8');
} else die(mysqli_error());
?>
When I do this it comes up with an error when opening it up saying that Excel doesn't recognise the file type, it opens the document but its drawn boxes around all the Turkish characters its tried to write.
I'm no PHP expert this is just information I've kind of pieced together.
Can anyone give me a hand?
Much appreciated
Moz
First of all, you appear to be creating a tab-delimited text file and then returning it to the browser with the MIME-type application/octet-stream and the file extension .xls. Excel might work out that's tab-delimited (but it sounds from your error as though it doesn't), but in any case you really should use the text/tab-separated-values MIME type and .txt file extension so that everything knows exactly what the data is.
Secondly, to create tab-delimited files, you'd be very wise to export the data directly from MySQL (using SELECT ... INTO OUTFILE), as all manner of pain can arise with escaping delimiters and such when you try to cook it yourself. For example:
SELECT * FROM users INTO OUFILE '/tmp/users.txt' FIELDS TERMINATED BY '\t'
Then you would merely need to read the contents of that file to the browser using readfile().
If you absolutely must create the delimited file from within PHP, consider using its fputscsv() function (you can still specify that you wish to use a tab-delimiter).
Always use the .txt file extension rather than .csv even if your file is comma-separated as some versions of Excel assume that all files with the .csv extension are encoded using Windows-1252.
As far as character encodings go, you will need to inspect the contents of your database to determine whether data is stored correctly or not: the best way to do this is to SELECT HEX(column) ... in order that you can inspect the underlying bytes. Once that has been determined, you can UPDATE the records if conversions are required.
I try to read image from database (blob) but i have problem becouse i don't know mime type of image. I have only tinyblob.
Can i read image and save it back to my hard disk?
The best solution is to store the mime-type in the DB at the same time you're inserting the image into the blob field. Otherwise you're going to have to the following EACH TIME the image is retrieved:
$image = $row['imageblob']; // $row = result row from DB query.
$finfo = new finfo(FILEINFO_MIME);
$mime_type = $finfo->buffer($image);
This gets to be expensive very quickly on a busy system, so best do the determination ONCE and then store that result.
Relevant PHP docs here.
Why not store the images on the hard disk all the time, and store in the Database a relative link based on a known directory?
Here's some code that I have used to get a logo (blob) from a mysql database
<img src="data:image/png;base64,<?php echo base64_encode($MyClass->getLogo())?>" alt="Logo" width="233" height="65" />
And the getLogo() function
public function getLogo()
{
if ($this->getId())
$query = "SELECT `logo` FROM Logos WHERE `logo_id` = '{$this->getId()}' LIMIT 1";
else
$query = "SELECT `logo` FROM Logos WHERE `logo_id` = '1' LIMIT 1";
$result = mysql_query($query);
if ($result)
$row = mysql_fetch_array($result);
else
return NULL;
return ($row['logo']);
}
I have this code (which thanks to the users of stackoverflow I got the markup I needed :) ). However, I have come to a road that I have no knowledge of what so ever. I need to output this formatted table of the query to a text file on the server.
<?php
// Make a MySQL Connection
mysql_connect("hostname.net", "user", "pass") or die(mysql_error());
mysql_select_db("database") or die(mysql_error());
// Get all the data from the "example" table
$result = mysql_query("SELECT * FROM cards ORDER BY card_id")
or die(mysql_error());
echo "";
echo " Name AgeTitlebar ";
// keeps getting the next row until there are no more to get
while($row = mysql_fetch_array( $result )) {
// Print out the contents of each row into a table
echo "";
echo $row['card_id'];
echo "";
echo $row['title'];
echo "";
echo $row['item_bar'];
echo "";
}
echo "";
?>
I know I could use something similar to
<?php
$myFile = "test.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = "Bobby Bopper\n";
fwrite($fh, $stringData);
fclose($fh);
?>
but I am sure that it cant be the best solution. So I guess my question is does anyone know how to achieve this?
The nicest solution, particularly if you are short on memory, would be to put the writing into the loop:
$fh = fopen('cards.csv', 'w');
// keeps getting the next row until there are no more to get
while($row = mysql_fetch_array( $result )) {
fputcsv($fh, array($row['card_id'], $row['title'], $row['item_bar']), "\t");
}
fclose('cards.csv');
Note that I have used fputcsv to output the data in CSV format (using a tab as the delimiter). This should be easy to read by hand, and will also be easily understood by, for instance, a spreadsheet program. If you preferred a custom format, you should use fwrite as in your question.
Have a look at:
http://dev.mysql.com/doc/refman/5.0/en/select.html
especially:
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
Something like this?
// Make sure the file exists, do some checks.
// Loop trough result set and append anything to the file.
while (false !== ($aRow = mysql_fetch_assoc($rResult))) {
$sCreateString = $aRow['field1'].';'.$aRow['field2'];
file_put_contents('example.txt', $sCreateString, FILE_APPEND);
}
// Done
If you need an exact dump of the database table, there are better options. (much better actually).
If you want to write a text file, then there's nothing wrong with what you've suggested.
There's lots of information in the PHP manual: http://www.php.net/manual/en/ref.filesystem.php
It depends entirely on how you want to store the data inside the file. You can create your own flat-file database format if you wish, and extract the data using PHP once you've read in the file.