Corrupt uploaded files with php and mysql - php

I need to upload and download files with php/mysql in my own little project.
The files are uploaded via form using POST and processed in the following way:
<?
$passName1 = $_FILES['passport1']['name'];
$tmpName1 = $_FILES['passport1']['tmp_name'];
$fileSize1 = $_FILES['passport1']['size'];
$fileType1 = $_FILES['passport1']['type'];
$fp1 = fopen($tmpName1, 'r');
$pass_1_content = fread($fp1, filesize($tmpName1));
fclose($fp1);
?>
Then I upload them using this function:
$passport1id = insert_user_file ($db, $passName1, $fileType1, $fileSize1, $pass_1_content);
function insert_user_file ($db, $name, $type, $size, $content) {
try {
echo "<br>start insert file $name";
$insertfile = new PDO("mysql:host=".$db['server'].";dbname=".$db['db'], $db['mysql_login'], $db['mysql_pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
// set the PDO error mode to exception
$insertfile->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// prepare sql and bind parameters
$stmt=$insertfile->prepare ("INSERT INTO files (name, size, type, content, created) VALUES (:name, :size, :type, :content, NOW())");
$stmt->bindParam(":name", $name);
$stmt->bindParam(":size", $size);
$stmt->bindParam(":type", $type);
$stmt->bindParam(":content", $content);
$stmt->execute();
$file_id = $insertfile->lastInsertId();
return $file_id;
}
catch(PDOException $e) {
echo 'error: '. $e->getMessage();
return false;
}
}
The presence of addslashes() to name/content of the file does not seem to make any difference at all.
Seems to work fine however when I get the file back with the function below, it appears to be corrupt:
get_file ($db, $_GET['id']);
function get_file ($db, $fileid){
try {
$get_file = new PDO("mysql:host=".$db['server'].";dbname=".$db['db'], $db['mysql_login'], $db['mysql_pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
$get_file->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$file = $get_file->prepare("SELECT * FROM files where fileid=:fileid");
$file->bindParam(":fileid", $fileid);
$file->execute();
$file_data = $file->fetch(PDO::FETCH_ASSOC);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header("Content-length: {$file_data['size']}");
header("Content-type: {$file_data['type']}");
header("Content-Disposition: attachment; filename={$file_data['name']}");
echo $file_data['content'];
exit;
}
catch(PDOException $e) {
//echo 'error: '. $e->getMessage();
return false;
}
}

I have resolved the issue! Stupid me, I should have put the whole code here, because it resulted into confusion!
<?php
ob_start();
session_start();
require_once 'functions.php';
/*
if(!isset($_SESSION['logged']) OR $_SESSION['logged'] == false){
header ("Location: index.php");
exit;
}
*/
//somecode here
//echo "logged in ok";
get_file ($db, $_GET['id']);
?>
The culprit is in the line 2 ob_start(); which overrode e warnings like:
Warning: Cannot modify header information - headers already sent by (output started at /sata2/home/users//functions.php:289) in /sata2/home/users//functions.php on line 130
The line 289 had several whitespaces after ?> //some spaces were here
This is a very silly mistake. Thank a lot to #MarcB for hinting that there might have been warnings I could miss. Never leave whitespaces after ?>

Related

PHP .pdf downloading script works partially

I am having trouble debugging a php script that I use for downloading .pdf files.
The script works fine for one user but doesn't work for another giving blank page.
What I am pretty sure is:
the part responsible for downloading works fine for both users
The query works fine and gets correct data from the serwer
All of the files are in the same directory (and as I already wrote it works perfectly for the first user)
Please give me a hint on where the bug might be or how to find it.
Thanks so much in advance.
Here's my code:
.htacces :
<Directory /faktury/>
Order deny,allow
Deny from all
</Directory>
html :
<form action="downloadfv.php" method="post">
<input type="text" name="fv" id="fv" value="$rowvariable" hidden />
<button type="submit"">Download</button>
</form>
downloadfv.php :
<?php
session_start();
if(!isset($_SESSION['zalogowany']))
{
header('Location: logowanie.php');
exit();
}
require_once "connect.php";
mysqli_report(MYSQLI_REPORT_STRICT);
$polaczenie = new mysqli($host, $db_user, $db_password, $db_name);
mysqli_query($polaczenie, "SET CHARSET utf8");
mysqli_query($polaczenie, "SET NAMES `utf8` COLLATE `utf8_polish_ci`");
if (mysqli_connect_errno())
{
echo "Could not connect to server" . mysqli_connect_error();
}
$idogloszenia = htmlspecialchars($_POST['fv'], ENT_QUOTES,'UTF-8');
$sql = "SELECT * FROM faktury WHERE user='{$_SESSION['user']}' AND idogloszenia = '$idogloszenia' ORDER BY idogloszenia DESC LIMIT 1";
$result = $polaczenie->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$file = "./faktury/".$row["nazwapdf"].".pdf";
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
}
} else {
echo " <div class='itemsname'>
<span style='padding:10px; font-size:90%'><u>No invoice available.</u></span>
</div>";
}
$polaczenie->close();
?>
The script works fine. The bug was inside my test database. It ocurred that I've had duplicated rows with similar data in them and the query selected wrong rows.
So the script can be used although as #mehdi pointed out it is not secure.
Thank you #chris85 for your hints.

PHP: Creating a MYSQL query inside a function

I have a function which performs an SQL query, "queryValue" the actual query to perform is passed later.
Function queryCreate($queryValue){
//DB connection variables
$host = "";
$user = "";
$password = "";
$database = "";
//create the connection
$conn = new mysqli($host, $user, $password, $database);
if ($conn->connect_error) {
die('DB Connection error: (' . $conn->connect_error . ') ' . $conn->connection_errorno);
}
$query = mysqli_query($conn,$queryValue) or die(mysqli_error($conn));
if ($result = mysqli_fetch_array($query,MYSQLI_ASSOC)) {
fputcsv($fh, array_keys($result));
fputcsv($fh, $result);
while ($result = mysqli_fetch_array($query,MYSQLI_ASSOC)) {
fputcsv($fh, $result);
}
}
return $queryValue;
}
I'm then attempting to assign the query value in a separate if statement. Below:
if(isset($_POST["Submit"]) && ($_POST['Weight'] == 'Weight')) {
$fh = csvCreate("Output Weight Null ".date('m-d-Y-His').".csv");
$queryValue = queryCreate('SELECT * FROM `table` WHERE WEIGHT = 0 OR weight IS NULL');
}
The problem I have is that the query does not appear to be being passed to the function. Could anyone suggest where I have gone wrong here? Many thanks.
The csvCreate function is shown here:
function csvCreate($filename){
header("Cache=Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename={$filename}");
header("Expires: 0");
header("Pragma: public");
$fh = #fopen( 'php://output', 'w' );
return $fh;
}
The problem is with the parameters of fputcsv() calls within queryCreate() function.
The file handler ($fh variable) is declared outside of queryCreate() function using the csvCreate() function:
$fh = csvCreate("Output Weight Null ".date('m-d-Y-His').".csv");
However,$fh is not passed as a parameter to queryCreate(), nor is $fh declared as a global variable, yet $fh variable is used to reference the file in all fputcsv() calls:
fputcsv($fh, array_keys($result));
In this case, $fh within queryCreate() will not refer to $fh variable where queryCreate() is called, but it will create a local $fh variable (empty at that), therefore the fputcsv() call will fail. The csv file is created in csvCreate(), this is independent from putting the values within the file.
The best solution would be to either pass $fh as a parameter to queryCreate(), or call csvCreate() from queryCreate(). In the latter case, the name of the dataset should be passed as a parameter.
UPDATE
Let's see some code as well:
//declaration of queryCreate()
Function queryCreate($queryValue, $reportName){ //$reportName is the name of the report
...
//create the csv file, put some parameter checks here as well
$fh = csvCreate($reportName.date('m-d-Y-His').".csv");
//and some error handling here
...
//output the contents of the query to the csv file
if ($result = mysqli_fetch_array($query,MYSQLI_ASSOC)) {
fputcsv($fh, array_keys($result));
fputcsv($fh, $result);
while ($result = mysqli_fetch_array($query,MYSQLI_ASSOC)) {
fputcsv($fh, $result);
}
}
... //should include closing of the csv file
} //end queryCreate()
...
//call the queryCreate()
if(isset($_POST["Submit"]) && ($_POST['Weight'] == 'Weight')) {
$queryValue = queryCreate('SELECT * FROM `table` WHERE WEIGHT = 0 OR weight IS NULL','Output Weight Null ');
}

Fatal error: Call to undefined function getRow() in PHPExcel export

I'm new in PHPExcel library and this is my first experience. I'm trying to export MySQL data to Ms Excel by formatting before. I've implemented a procedure that simply formats headings of the table with bold fonts and saves them with all relevants data to the spreadsheet. However, when I run the procedure, it displays the following error:
Fatal error: Call to undefined function getRow() in C:\Xampp\htdocs\test.php on line 182
Here is the PHP code:
require_once 'PHPExcel.php';
require_once 'PHPExcel/IOFactory.php';
require_once 'PHPExcel/Writer/Excel2007.php';
// create mysql query
$query_export = "SELECT * FROM `table1` ORDER BY `date` ASC";
// execute query
$result = mysqli_query($GLOBALS['mysqli'], $query_export) or die ("<b>Couldn't execute SQL query:</b> " . mysqli_error($GLOBALS['mysqli']));
try {
$sheet = new PHPExcel();
// set metadata
$sheet->getProperties()->setCreator('www.example.com')
->setLastModifiedBy('www.example.com')
->setTitle('Report on Table')
->setKeywords('report tables etc.');
// set default settings
$sheet->getDefaultStyle()->getAlignment()->setVertical(
PHPExcel_Style_Alignment::VERTICAL_TOP);
$sheet->getDefaultStyle()->getAlignment()->setHorizontal(
PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
$sheet->getDefaultStyle()->getFont()->setName('Calibri');
$sheet->getDefaultStyle()->getFont()->setSize(12);
// get reference to active spreadsheet in workbook
$sheet->setActiveSheetIndex(0);
$activeSheet = $sheet->getActiveSheet();
// populate with data
$row = getRow($result); // line 182
$colHeaders = array_keys($row);
$col = 'A';
$rownum = 1;
// set column headings
foreach ($colHeaders as $header) {
$activeSheet->setCellValue($col . $rownum, $header);
$activeSheet->getStyle($col . $rownum)->getFont()->setBold(true);
$activeSheet->getColumnDimension($col)->setAutoSize(true);
$col++;
}
// populate individual cells with data
do {
$col = 'A';
$rownum++;
foreach ($row as $value) {
$activeSheet->setCellValue($col++ . $rownum, $value);
}
} while ($row = getRow($result));
// setting headers
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename=Export.xlsx');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
$writer = PHPExcel_IOFactory::createWriter($sheet, 'Excel2007');
$writer->save('php://output');
exit();
} catch (Exception $e) {
$error = $e->getMessage();
}
// display error
if (isset($error)) {
echo "<p>" .$error. "</p>";
}
// free resultset
mysqli_free_result($result);
// close db connection
$GLOBALS['mysqli']->close();
exit();
Any help is appreciated.
UPDATE
The following tutorial is used to create above mentioned code:
http://www.youtube.com/watch?v=L6MQQvBi-ks
I believe you need to define getRow or use something like this:
http://php.net/manual/en/mysqli-result.fetch-row.php

PHP not creating downloadable CSV file

I am trying to pull out data from my database using php and exporting it into a downloadable CSV file that can be opened with excel. I am able to do this when i use mysql however, many have advised to not include mysql syntax in my code as its being deprecated and instead i should use mysqli. I have changed my code but now my code is not working. Does anyone know why that is?
mysql version (working version)`
mysql_connect('localhost', 'xxxxx', 'xxxxx') or die('connect');
mysql_select_db('db') or die('select');
$result = mysql_query('SELECT * bodyshops_master_network') or die('query');
if(mysql_num_rows($result) == 0)
{
die('no data');
}
$fh = tmpfile() or die('tmpfile');
$cols = array_keys(mysql_fetch_assoc($result));
fputcsv($fh, $cols);
mysql_data_seek($result, 0); // set result row pointer back to first row
while($row = mysql_fetch_assoc($result))
{
fputcsv($fh, $row);
}
rewind($fh);
$text = fread($fh, 999999);
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="download.csv"');
header('Content-Length: ' . strlen($text));
echo $text;
exit;
mysqli version (not working):
$mysqli = new mysqli("localhost", "xxxxx", "xxxxx", "db");
if (mysqli_connect_errno())
{
printf("Connect failed: ", mysqli_connect_error());
exit();
} else
{
$result = "SELECT * FROM bodyshops_master_network";
if(mysqli_num_rows($result) == 0)
{
die('no data');
}
$fh = tmpfile() or die('tmpfile');
$cols = array_keys($result->fetch_assoc());
fputcsv($fh, $cols);
$result->data_seek(0); // set result row pointer back to first row
while($row = $result->fetch_assoc())
{
fputcsv($fh, $row);
}
rewind($fh);
$text = fread($fh, 999999);
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="download.csv"');
header('Content-Length: ' . strlen($text));
echo $text;
exit;
Check phpinfo to see that mysqli extension is enabled.
Remove/comment the header calls so that you receive the output as plain HTML so that you notice if any message shows up (due to die or coding error) or if you actually get the data.
Also note that you loose the date of the first record you retrieve because you call:
$cols = array_keys(mysql_fetch_assoc($result));
respectively
$cols = array_keys($result->fetch_assoc());
What is not working?
Are you getting any errors?
Is the file empty, is there any file downloading?
Maybe errors aren't enabled, try this:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
?>
I'm new on StackOverflow, I think this would help. (I speak spanish, I hope you to understand my english :D )
I've been looking for a simply way to use mysqli and download a csv file that could be read by excel without UTF-8 problems (using ñ,á,ü...). I didn't found it, so I created one by myself (learning from Google and StackOverflow answers), after some hours I got something that works finally.
This is a Class that connects with the database and the functions will do whatever you want using mysqli and PHP. In this case, calling this class (require or include), just use the "downloadCsv()" function.
As an example, this would be the "class.php" file:
<?php
class DB{
private $con;
//this constructor connects with the database
public function __construct(){
$this->con = new mysqli("Your_Host","Your_User","Your_Pass","Your_DatabaseName");
if($this->con->connect_errno > 0){
die('There was a problem [' . $con->connect_error . ']');
}
}
//create the function that will download a csv file from a mysqli query
public function downloadCsv(){
$count = 0;
$header = "";
$data = "";
//query
$result = $this->con->query("SELECT * FROM Your_TableName");
//count fields
$count = $result->field_count;
//columns names
$names = $result->fetch_fields();
//put column names into header
foreach($names as $value) {
$header .= $value->name.";";
}
}
//put rows from your query
while($row = $result->fetch_row()) {
$line = '';
foreach($row as $value) {
if(!isset($value) || $value == "") {
$value = ";"; //in this case, ";" separates columns
} else {
$value = str_replace('"', '""', $value);
$value = '"' . $value . '"' . ";"; //if you change the separator before, change this ";" too
}
$line .= $value;
} //end foreach
$data .= trim($line)."\n";
} //end while
//avoiding problems with data that includes "\r"
$data = str_replace("\r", "", $data);
//if empty query
if ($data == "") {
$data = "\nno matching records found\n";
}
$count = $result->field_count;
//Download csv file
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=FILENAME.csv");
header("Pragma: no-cache");
header("Expires: 0");
echo $header."\n".$data."\n";
}
?>
After creating the "class.php" file, in this example, use that function on "download.php" file:
<?php
//call the "class.php" file
require_once 'class.php';
//instantiate DB class
$export = new DB();
//call function
$export->downloadCsv();
?>
After download, open the file with MS Excel.
I hope this help you, I think I wrote it well, I didn't feel comfortable with the text and code field.

Downloading BLOB file with Oracle and PHP

Using PHP, I'm trying to download a blob file that has already been uploaded to an Oracle 10g database. I've seen and imitated numerous examples I've found. When I access the page a File Download dialog appears allowing me to Open or Save. If I click Open, media player comes up as it should but never retrieves the file. If I choose Save, I always get an error message stating "Internet Explorer was not able to open this Internet site. The requested site is either unavailable or cannot be found. Please try again later."
Below is my code which is pretty straight forward and pretty much like the examples I've found.
<?php
header('Content-Disposition: attachment; filename='.$_GET['fileName']);
header('Content-length: '.$_GET['fileSize']);
header('Content-type: '.$_GET['mimeType']);
require_once("Include/Application.php");
$connection = oci_connect ($userID, $password, $TNS);
$phpCur = oci_new_cursor($connection);
$stmt = oci_parse($connection, "BEGIN MOR.DOWNLOAD_ATTACHMENT (:morID, :attachmentType, :phpCur); END;");
oci_bind_by_name($stmt, ":morID", $_GET['morID'], -1);
oci_bind_by_name($stmt, ":attachmentType", $_GET['attachmentType'], -1);
oci_bind_by_name($stmt, "phpCur", $phpCur, -1, OCI_B_CURSOR);
oci_execute($stmt);
oci_free_statement($stmt);
$output = '';
oci_execute($phpCur);
while( $row = oci_fetch_array($phpCur) )
$output .= $row['ATTACHMENT_BL'];
oci_free_statement($phpCur);
oci_close($connection);
echo $output;
exit;
?>
Use your db query and excecute first here is the data field is blob data:
$sql="SELECT FILE_NAME,data,length(data) as filesize FROM branch_data where id='$id'";
$r = $db->execute($sql);
$filename=$r->data[0]['FILE_NAME'];
$d=$r->data[0]['DATA'];
$filesize = $r->data[0]['FILESIZE'];
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' .$filesize);
echo $d->load();
Add more error handling to your script. Any of the oci* function can fail and then subsequent steps will also fail. The documentation tells you what happens if a function fails and what the return value will be. E.g.
Return Values
Returns a connection identifier or FALSE on error.
If you set the Content-type header as late as possible, i.e. directly before the first output, you can send plain text or html that contains some sort of error message instead.
<?php
// error_reporting/ini_set: for testing purposes only.
error_reporting(E_ALL); ini_set('display_errors', 1);
require_once("Include/Application.php");
$connection = oci_connect ($userID, $password, $TNS);
if ( !$connection) {
die('database connection failed');
}
$phpCur = oci_new_cursor($connection);
if ( !$phpCur) {
die('creating cursor failed');
}
$stmt = oci_parse($connection, "BEGIN MOR.DOWNLOAD_ATTACHMENT (:morID, :attachmentType, :phpCur); END;");
if ( !$stmt) {
die('creating statement failed');
}
// and so on and on. Test the return values of each oci* function.
oci_close($connection);
header('Content-Disposition: attachment; filename='.$_GET['fileName']); // at least at basename() here
header('Content-length: '.$_GET['fileSize']); // strange...
header('Content-type: '.$_GET['mimeType']); // possible but still strange...
echo $output;
exit;

Categories