load default image if database connection fails - php

I am attempting to build a database driven site whereby images are loaded via a php script like so;
<img src="get_image.php?holderID=2">
I can get images to load from a folder outside the root directory when the database is accessible but I also want to be able to load a default image if there is a failure with making the database connection. The DB connection is initiated form a separate php connection file mysqli_template_connect.php;
DEFINE('DB_USER', 'someusername');
DEFINE('DB_PASSWORD', 'amnesia');
DEFINE('DB_HOST', 'localhost');
DEFINE('DB_NAME', 'template');
$dbc = #mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
and then config.inc.php sets some constants, one of which is for all DB connections;
define('MYSQL', '../../../dbconnect/mysqli_template_connect.php');
The get_image.php file then has a database connection conditional;
require('includes/config.inc.php');
REQUIRE(MYSQL);
$holderID = $_GET['holderID'];
if(!$dbc){
$image_name = 'img/unavailable.png';
$info = getimagesize($image_name);
header("Content-Type: {$info['mime']}\n");
readfile($image_name);
}
else {
$query = "SELECT imageID FROM image_holder WHERE image_holderID = $holderID ";
$result = #mysqli_query($dbc, $query);
$number_rows = mysqli_num_rows($result);
if ($number_rows == 1) {
$row = mysqli_fetch_array($result, MYSQLI_NUM);
$imageID = $row[0];
}
else {
$imageID = FALSE;
}
if ($imageID) {
$query = "SELECT file_name FROM image WHERE imageID = $imageID";
$result = mysqli_query($dbc, $query);
$number_rows = mysqli_num_rows($result);
if ($number_rows == 1) {
$row = mysqli_fetch_array($result, MYSQLI_NUM);
$image_name = '../../../uploads/' . $row[0];
}
else {
$image_name = 'img/unavailable.png';
}
}
else {
$image_name = 'img/unavailable.png';
}
$info = getimagesize($image_name);
header("Content-Type: {$info['mime']}\n");
readfile($image_name);
mysqli_close($dbc);
}
If I disable the MYSQL database in XAMP, the default image unavailable.png will not load even though the header and readfile section of code is virtually the same in the section of code that does work. I'm quite a newbie to all this so any ideas on loading the default image would be appreciated.

Depending on the database object you are using (MySQLi/PDO/etc), you can check if they connected. PDO returns a boolean that you can run against.
Since PDO is the most popular, I will provide an example of that. If you use something else, feel free to comment and I can clarify.
$connected = true;
if (!extension_loaded('PDO'))
{
$connected = false;
}
if (!extension_loaded('pdo_mysql'))
{
$connected = false;
}
try
{
$pdo = new PDO("mysql:host={$host};dbname={$db}", $user, $pass);
}
catch(PDOException $e)
{
$connected = false;
}
if(!$connected){ /* Load default image */ }
Note: just make sure you use the correct image headers.

Instead of
$dbc = #mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
Use
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
hopefully it should work..

I have similar code that do the almost the same thing.
I suspect it was the header, since I have a bit more info added to the header. No harm for you to try out.
header('Content-Description: File Transfer');
header('Content-Type: '. $file_content_type);
header('Content-Length: ' . filesize($file_full_path));
header('Content-Disposition: inline; filename=' . $file_name);
readfile($file_full_path);

Related

Loop through and download multiple CSVs from Database in PHP

I have the following code which I am using to download a CSV of the data to a file called Out of Area.csv
<?php
// START EXPORT OF LTHT DATA //
exportMysqlToCsv('Out of Area.csv');
// export csv
function exportMysqlToCsv($filename = 'Out of Area.csv')
{
$conn = dbConnection();
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql_query = "SELECT * FROM MDSData WHERE Downloaded IS NULL ORDER BY RegisteredCCG";
// Gets the data from the database
$result = $conn->query($sql_query);
$f = fopen('php://temp', 'wt');
$first = true;
while ($row = $result->fetch_assoc()) {
if ($first) {
fputcsv($f, array_keys($row));
$first = false;
}
fputcsv($f, $row);
} // end while
$sql_query = "UPDATE MDSData SET Downloaded='YES' WHERE Downloaded IS NULL";
// Gets the data from the database
if ($conn->query($sql_query) === TRUE) {
} else {
}
$conn->close();
$size = ftell($f);
rewind($f);
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Length: $size");
// Output to browser with appropriate mime type, you choose ;)
header("Content-type: text/x-csv");
header("Content-type: text/csv");
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=$filename");
fpassthru($f);
exit;
}
// db connection function
function dbConnection(){
$servername = "servername";
$username = "username";
$password = "password";
$dbname = "databasename";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
return $conn;
}
header('location:csv-upload-mds.php?week='.$SelectedWeek);
?>
However I have a column in my table called 'TownName' and I would like to loop through creating a CSV Named 'Out of Area - The Town Name Here.csv' for example 'Out of Area - Berkshire.csv'
Currently i've got to the stage where I can make it download 1 file with all the data in, however my issue comes when trying to download multiple files. Even if I duplicate the exportMysqlToCsv() call I get an error as this function can only be called once. So I need to put the loop inside an if statement I guess...
My thoughts are something like the following
$sqlquery = "SELECT * FROM MDSData WHERE Downloaded IS NULL GROUP BY REGISTERED CCG"
$result = $conn->query($sql_query);
while ($row = $result->fetch_assoc()) {
// Now I've looped through each CCG for each one I can set the file name and add the data to the file.
$filename = "Out of Area - " . $row["TownName"]. ".csv";
$sql_query = "SELECT * FROM MDSData WHERE Downloaded IS NULL ORDER BY RegisteredCCG";
// Gets the data from the database
$result = $conn->query($sql_query);
$f = fopen('php://temp', 'wt');
$first = true;
while ($row = $result->fetch_assoc()) {
if ($first) {
fputcsv($f, array_keys($row));
$first = false;
}
fputcsv($f, $row);
} // end while of inside loop
} // end while of 1st SQL query
However whilst I belive my idea is solid, I'm struggling to put it all together and looking for a little help.
Thanks

Create zip archive out of file from MySQL using PHP

I am trying to put a XML file from MySQL database to a zip archive before downloading. I am able to create zip file but Windows is giving error while opening it.
error msg: window cannot open the foler.
filename.zip is invalid
Here is my code:
<?php
if(isset($_GET['id']))
{
$id = intval($_GET['id']);
if($id <= 0) {
die('The id is invalid!');
}
else
{
// Connect to the database
$dbLink = new mysqli('localhost', 'root', 'root', 'db');
if(mysqli_connect_errno()) {
die("MySQL connection failed: ". mysqli_connect_error());
}
$zip = new ZipArchive();
$filename = "export_".date('Y.m.d H.i').".zip";
if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true)
{
echo "Cannot Open for writing";
}
$zip->addEmptyDir('Section');
$query = "SELECT name,data FROM file_section WHERE id ='$id'";
$result = $dbLink->query($query);
if($result->num_rows == 1)
{
// Get the row
$row = mysqli_fetch_array($result);
}
while($row = mysql_fetch_array($result))
{
$zip->addFile($row['data'], "{$row['name']}.xml");
}
$zip->close();
header("Content-disposition: attachment; filename='.$filename'");
header('Content-type: application/zip');
readfile($fileName);
}
// Free the mysqli resources
mysqli_free_result($result);
}
else {
echo "Error! Query failed: <pre>{$dbLink->error}</pre>";
}
mysqli_close($dbLink);
?>
P.S.: I have limited PHP knowledge.
Test this : create a temp file before addFile your zip object
see http://php.net/manual/en/ziparchive.addfile.php
addFile method wait first parameter a filename (the path to the file to add)
Here is the working solution that I got later. Its valid for one single file id input.
<?php
// Make sure an id was passed
if (isset($_GET['ids'])) {
// Get the id into string (in case of an array)
$id_pass = implode(",",$_GET['ids']);
// Make sure the name is in fact a valid
if ($id_pass <= 0) {
die ('No ID Selected!');
} else
{
// Connect to the database
$dbLink = new mysqli('localhost', 'root', 'password', 'DB Name');
if (mysqli_connect_errno()) {
die("MySQL connection failed: " . mysqli_connect_error());
}
// Fetch the file information
$query = "select id, name, data from datatable where id = {$id_pass};";
$result = $dbLink->query($query);
if ($result) {
// Make sure the result is valid
if ($result->num_rows == 1) {
// Get the row
$row = mysqli_fetch_assoc($result);
//zip function
$zip = new ZipArchive();
$filename = "export_" . date('Y.m.d H.i.s') . ".zip";
if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true) {
echo "Cannot Open for writing";
}
$ext = $row['name'] . ".xml"; // taking file name from DB and adding extension separately
$zip->addFromString($ext, $row['data']); //adding blob data from DB
$zip->close();
header("Content-disposition: inline; filename='.$filename'");
header('Content-type: application/zip');
readfile($filename);
unlink($filename);
}
}
// Free the mysqli resources
mysqli_free_result($result);
mysqli_close($dbLink);
}
}

How to avoid including login credentials on each php page, storing the credentials in a single page and adjusting code to match adjustments

I have the following code to do a simple image upload and store a few data, however I want to remove the section(s) of the code that have the direct database username password and host, with a simple include("config.php") in the heading. So what I am asking apart from the include("config.php") line how would I make adjustments to the code example:$conn = $db->prepare($query); an so on
<?php
include("config.php");
define('UPLOAD_PATH', $_SERVER['DOCUMENT_ROOT'] . 'photohandling/uploads/');
define('DISPLAY_PATH', '/photohandling/uploads/');
define('MAX_FILE_SIZE', 2000000);
$permitted = array('image/jpeg', 'image/pjpeg', 'image/png', 'image/gif','image/tiff');
$dames2=time();
$db_host = 'localhost';
$db_user = 'root';
$db_pass = 'password';
$db_name = 'test';
if (!empty($_POST)){
$fileName = $_FILES['userfile']['name'];
$tmpName = $_FILES['userfile']['tmp_name'];
$fileSize = $_FILES['userfile']['size'];
$fileType = $_FILES['userfile']['type'];
$fname=$_POST['fname'];
$lname=$_POST['lname'];
$age=$_POST['age'];
$acquirer_bin=$_POST['acquirer_bin'];
$terminal_id=$_POST['terminal_id'];
$trace_id=$_POST['trace_id'];
// get the file extension
$ext = substr(strrchr($fileName, "."), 1);
// generate the random file name
$randName = md5(rand() * time());
// image name with extension
$myfile = $acquirer_bin.$trace_id.$dames2.$randName . '.' . $ext;
// save image path
$path = UPLOAD_PATH . $myfile;
if (in_array($fileType, $permitted) && $fileSize > 0 && $fileSize <= MAX_FILE_SIZE) {
//store image to the upload directory
$result = move_uploaded_file($tmpName, $path);
if (!$result) {
echo "Error uploading image file";
exit;
} else {
$db = new mysqli("localhost", "root", "hynes21", "test");
if (mysqli_connect_errno()) {
printf("Connect failed: %s<br/>", mysqli_connect_error());
}
$query =
"INSERT INTO tester(fname,lname,age, acquirer_bin, terminal_id, trace_id,photo_name, size, type, file_path) VALUES(?,?,?,?,?,?,?,?,?,?)";
$conn = $db->prepare($query);
if ($conn == TRUE) {
$conn->bind_param("ssiisisiss",$fname,$lname,$age,$acquirer_bin,$terminal_id,$trace_id, $myfile, $fileSize, $fileType, $path);
if (!$conn->execute()) {
echo 'error insert';
} else {
echo 'Success!<br/>';
echo '<img src="' . DISPLAY_PATH . $myfile . '"/>';
}
} else {
die("Error preparing Statement");
}
}
} else {
echo 'error upload file';
}
} else {
echo 'error';
}
?>
You really shouldn't define database credentials in code. A solid why to do this is to use a configuration file. PHP provides a built in function called parse_ini_file that is perfect for retrieving data from config files (in a certain format ofc).
Here is an example of a ini file that can be parsed by parse_ini_file [docs]
[db]
host = localhost
user = root
pass = password
database = test
As you can see the format of the file is very similar to the php.ini file.
Keep this db.ini file in a place that is not accessible by the web server but can be read by PHP.
Here is a function that can utilize the data in the ini file and create a new mysqli object for you.
// somefile.php
function new_db() {
$info = parse_ini_file('db.ini', true);
return new mysqli($info['db']['host'],
$info['db']['user'],
$info['db']['pass'],
$info['db']['database']);
}
To use your new_db function.
require_once 'somefile.php';
$db = new_db();
$stmt = $db->prepare($query);
// ...
If I understand correctly, you want to use the values defined in config.php. If so, this is all you need to do:
config.php
define(DB_HOST, 'localhost');
define(DB_USER, 'root');
define(DB_PASS, 'hynes21');
define(DB_NAME, 'test');
php file from where config.php is included
Option 1:
$db_host = DB_HOST;
$db_user = DB_USER;
$db_pass = DB_PASS;
$db_name = DB_NAME;
$db = new mysqli($db_host, $db_user, $db_pass, $db_name);
Option 2:
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
And yeah, a heap of ppl will tell you to use PDO instead of mysqli. Indeed you should, but that's doesn't give you an answer to your question :)
Let's say in your config.php file you have this:
$dbHost = 'localhost';
$dbUser = 'root';
$dbPass = 'hynes21';
$dbName = 'test';
Then in your code above you would replace this line:
$db = new mysqli("localhost", "root", "hynes21", "test");
with this:
$db = new mysqli($dbHost, $dbUser, $dbPass, $dbName);
and the rest of your code should just work, thanks to variable scoping.
You could also put the db connection in the config.php file as well, which would allow you to destroy the stored connection info variables so they wouldn't be hanging around anywhere for accidental output:
$dbHost = 'localhost';
$dbUser = 'root';
$dbPass = 'hynes21';
$dbName = 'test';
$db = new mysqli($dbHost, $dbUser, $dbPass, $dbName);
unset($dbHost);
unset($dbUser);
unset($dbPass);
unset($dbName);
This would mean every page load would have the overhead of calling mysqli(), even if that page didn't use the database. But if you have a data driven site then virtually every page will want to call mysqli() anyway so that's not such a big deal.
Later on you may want to look in to using a database wrapper so you don't have to store your DB connection in a locally scoped variable, but this approach will work just fine for simple applications.

Force multiple file download with PHP

I am trying to write a little script to backup all my localhost databases at once in seperate files. Currently my script does the backup part but does the download in one file. (So i get something like 30MB information_schema_backup.sql ) What i want is db_name_backup.sql for each database. Here is my code.
<?
function backup_dbs()
{
global $db_name;
global $dosyaadi; //dosyaadi means filename.
$return='';
/*
Backup Part Here;
I can share if anyone needs.
I will post this on my blog anyway.
*/
//save file
$dosyaadi=$db_name.'-backup-'.time().'.sql';
header("Content-type: application/octet-stream");
header("Content-disposition: attachment;filename=$dosyaadi");
echo $return;
}
$db_host = 'localhost';
$db_user = 'root';
$db_pass = '';
$db = mysql_connect($db_host, $db_user, $db_pass);
mysql_query("SET NAMES 'utf8'", $db);
mysql_query("SET CHARACTER SET utf8", $db);
mysql_query("SET COLLATION_CONNECTION = 'utf8_general_ci'", $db);
$res = mysql_query("SHOW DATABASES");
while ($row = mysql_fetch_assoc($res)) {
$db_name = $row['Database'];
mysql_select_db($db_name, $db);
backup_dbs();
}
die();
?>
Thanks in advance.

Attempting to display an image in PHP from a MySQL database

I attempted to display the image using PHP with the following code
<?php
header('Content-type: image/png');
$port = "*";
$server = "*:".$port;
$dbname ="*";
$user = "*";
$conn = mysql_connect ("$server", "$user", "$pass") or die ("Connection
Error or Bad Port");
mysql_select_db($dbname) or die("Missing Database");
$speakerPic = $_POST['speakerPic'];
$query = "SELECT Speaker.speaker_picture AS image FROM Speaker JOIN Contact c USING(contact_id)
WHERE c.lname = '";
$query .= $speakerPic."';";
$result = mysql_query($query,$dbname);
$result_data = mysql_fetch_array($result, MYSQL_ASSOC);
echo $result_data['image'];
?>
I keep on receiving this error, The image “.../query2.php” cannot be displayed because it contains errors.
Sorry to keep on bugging you guys, but can anyone tell what the problem is?
Not going to lie, there is a lot of bad with the OP code.
You should be pulling images from the database by id, not some string
You are not sanitizing the var being used in the query
You are not serving a default image if one doesn't exist
Also, I would suggest storing file uris in your database, not the actual image (blob). You should store a pointer to an image on your filesystem.
Not going to clean up the code too much, just make it less bad. I'd suggest something along these lines (untested):
// Utility.php
class Utility
{
/**
*
* #param mixed $id is abstract, could be name or an actual id
* #return string?
*/
public static function getImage($id)
{
try {
$port = "*";
$server = "*:".$port;
$dbname ="*";
$user = "*";
$conn = mysql_connect ("$server", "$user", "$pass");
if (!$conn) {
throw new Exception("Connection Error or Bad Port");
}
if (!mysql_select_db($dbname)) {
throw new Exception("Missing Database");
}
$query = "SELECT Speaker.speaker_picture AS image FROM Speaker JOIN Contact c USING(contact_id) WHERE c.lname = " . mysql_real_escape_string($id). ";";
$result = mysql_query($query,$dbname);
$result_data = mysql_fetch_array($result, MYSQL_ASSOC);
if (!isset($result_data['image'])) {
throw new Exception('Image not found');
}
echo $result_data['image'];
} catch Exception($e) {
error_log($e->getMessage();
return file_get_contents('/path/to/some/default/image.png');
}
}
}
// image.php
require_once 'Utility.php';
header('Content-type: image/png');
ob_start();
Utility::getImage($_POST['speakerPic']);
$image = ob_get_flush();
echo $image;

Categories