I am using PHPExcel to generate a spreadsheet.
If I generate and download at the same time, everything is fine.
But when I save to a MediumBlob in my MySQL and then download it, MSExcel says it is not ok.
I am using the same headers in both situations.
Gera is the function that generates the file:
$agora=date("Y-m-d H:i:s");
$relatorio_rh_xls=$dbHandle->real_escape_string(RelatorioBaseRH::Gera($ciclo,$dbHandle));
$qry="insert into tb_relatorio_rh (id_avaliacao_ciclo,relatorio_base_RH_xls,inicio_vigencia,fim_vigencia) values ( $ciclo,'".$relatorio_rh_xls."','".$agora."',null)";
$result4=$dbHandle->query($qry);
And then to retrieve it:
$query = "SELECT $nomeRelatorio, OCTET_LENGTH($nomeRelatorio) as tamanho " .
"FROM tb_relatorio_rh WHERE id_avaliacao_ciclo = '$id_avaliacao_ciclo' and fim_vigencia is null order by inicio_vigencia desc";
$resultadoConsulta= $dbHandle->query($query);
$qtdeLinhas=$resultadoConsulta->num_rows;
if ($qtdeLinhas>0) {
$fetBuscaRelatorio = $resultadoConsulta->fetch_assoc();
$relatorio=$fetBuscaRelatorio[$nomeRelatorio];
$size=$fetBuscaRelatorio['tamanho'];
$type= substr($nomeRelatorio, -3, 3);
if ($type == "xls"){ $type="xlsx";}
$nomeAvaliado= str_replace(' ','_',$nomeAvaliado);
$nomeDownload=substr($nomeRelatorio, 0, strlen($nomeRelatorio)-4) .'_' . $nomeAvaliado .'.'. $type;
header("Content-Length: $size");
header("Content-Type: $type");
header("Content-Disposition: attachment; filename=$nomeDownload");
print $relatorio;
}
The problem was with another php file I was including with include_once(anotherfile.php).
That anotherfile.php had blank lines after ?> closing tag.
Related
I'm trying to extract a BLOB from mysql and send it to the requester without saving it on the server. I've gotten it to work with PDF files, but some of our clients want xls files. When getting the xls file, the downloaded file is garbage. In HxD it looks like it is putting an extra 11 bytes on the front of the file.
Here is my code, both working and not working:
function blob_download_xls() {
$mysqli = openMySQLconnetion();
$sql = "SELECT * FROM Uploads;";
$results = $mysqli->query($sql);
$row = $results->fetch_assoc();
$bytes = $row['filedata'];
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="report.xls"');
print $bytes;
}
function blob_download_pdf() {
$mysqli = openMySQLconnetion();
$sql = "SELECT * FROM Uploads;";
$results = $mysqli->query($sql);
$row = $results->fetch_assoc();
$bytes = $row['filedata'];
header("Content-type: application/pdf");
header('Content-Disposition: inline; filename="report.pdf"');
print $bytes;
}
Any idea what I'm doing wrong?
I asked this question with a new account without realizing that I already had an account here. I've solved the problem and it was stupid.
When writing my function.php, I put a closing tag '?>' on the end of the file. After this tag was a 0d0a for a line feed return and then 9 20's for 9 spaces. I removed the closing tag and now it works perfectly.
The correct way to deal with this is to die() immediately after printing the bytes, before the server has a chance to output any HTML that may succeed the PHP code.
function blob_download_xls() {
$mysqli = openMySQLconnetion();
$sql = "SELECT * FROM Uploads;";
$results = $mysqli->query($sql);
$row = $results->fetch_assoc();
$bytes = $row['filedata'];
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="report.xls"');
print $bytes;
die();
}
I have created a upload form and a php file which extract the name, size, type of the file and stores it in a database upload script, in table files. The file is also given a uniqid which is also stored in the same table.
Now I am trying to build up a download.php file where I want that when a specific link with the uniqid in is opened the script look in databse for the file searching for the uniqid and show the information against it.?
Here is my upload.php
<?php
include('config.php');
function bytesToSize1024($bytes, $precision = 300) {
$unit = array('B','KB','MB');
return #round($bytes / pow(1024, ($i = floor(log($bytes, 1024)))), $precision).' '.$unit[$i];
}
$FileName = $_FILES['filename']['name'];
$FileType = $_FILES['filename']['type'];
$FileSize = bytesToSize1024($_FILES['filename']['size'], 1);
$Fileid = uniqid(rand());
$tmp_name = $_FILES["filename"]["tmp_name"];
if ($_FILES["filename"]["error"] > 0)
{
echo "Apologies, an error has occurred.";
echo "Error Code: " . $_FILES["fileToUpload"]["error"];
}
else
{
move_uploaded_file($_FILES["filename"]["tmp_name"],
"C:\wamp\www\upload\upload" . $_FILES["filename"]["name"]);
}
$query2 = "INSERT INTO files (id, name, size, type) VALUES ('$Fileid', '$FileName', '$FileSize', '$FileType')";
$result2 = mysql_query($query2);
echo <<<EOF
<p>Your file: {$FileName} has been successfully received.</p>
<p>Type: {$FileType}</p>
<p>Size: {$FileSize}</p>
<p>Temp Foler: {$tmp_name}</p>
<p>Download Link: localhost/upload/download.php?=$Fileid
EOF;
?>
Please first tell me which kind of link I should create like. localhost/download.php?=uniqid
will the above example work and how to make it work. I am confused?
Here I have tried to create a download.php file but it is not good
<?php
include('config.php');
$query = "SELECT * FROM files";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
?>
<?php
echo <<<EOF
File Name: <?php echo $row['name']; ?>
$row
EOF;
?>
This is the code you need. Consider storing byte count in the database for file size.
Of course it might need some changes to be exactly what you want.
<?php
include('config.php');
//get id from GET method and make sure that it's safe to be used in the query
$id=mysql_real_escape_string($_GET['id']);
$query = "SELECT * FROM `files` WHERE `id`='$id'";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
if (count($row)!=1) //check if our unique record has been found
die('Sorry but we could not find this file!');
$row=$row[0];
//send download headers
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$row['name']);
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: no-cache');
header('Content-Length: ' .$row['size']);
readfile(upload" . $row['name']); //I recommend you to change the path and file name of your uploaded files!
?>
Link example: http://yourdomain.com/download.php?id=123
From a php script (PHP 5.3.10-1 on Ubuntu3.6) I connect to an MSSQL Server and I would like to retrive image data from image field type. And I want to print it.
I can get the data from MSSQL but I can't print/echo it as a valid image. How can I print/echo/save it?
$db= new PDO('odbc:MYODBC', '***', '***');
$stmt = $db->prepare("USE database");
$stmt->execute();
$tsql = "SELECT image
FROM Pics
WHERE id = 12";
$stmt = $db->prepare($tsql);
$stmt->execute();
$stmt->bindColumn(1, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
header("Content-Type: image/jpg");
echo($lob); //not an image: 424df630030000000000360000002800 ...
imagecreatefromstring($lob); // Data is not in a recognized format ...
$lob = fopen('data://text/plain;base64,' . base64_encode($lob), 'r'); //Resource
fpassthru($lob); //not an image: 424df63003000000000036000000280000 ...
PHP script encoding: UTF-8.
In /etc/freetds/freetds.conf
[MYODBC]
host = myhost.com
client charset = UTF-8
tds version = 7
((With sqlsrv on the server of MSSQL I could use this:
$image = sqlsrv_get_field( $stmt, 0,
SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
header("Content-Type: image/jpg");
fpassthru($image);
))
UPDATE:
echo base64_decode($lob); //Not an image: γnτΣ}4ΣM4ΣM4ί4ΣM4ΫΝ4ΣM4s...
Try adding the following headers :
Content-Disposition
Content-Transfer-Encoding
Content-Length
In PHP code :
header('Content-Type: image/jpg');
header('Content-Disposition:attachment; filename="my_file.jpg"');// Set the filename to your needs
header('Content-Transfer-Encoding: binary');
header('Content-Length: 12345');// Replace 12345 with the actual size of the image in bytes
I was recently fighting with a similar storage issue. It turned out that I was quoting my binary image data before insert into the database table. So, make sure you are not adding quotes and turning it into a string - like I accidentally did.
Here's the prep work that is done on an existing local file to get the proper data to store into your database. Also, make sure you have bin2hex() available or get a replacement version of the function.
function prepareImageDBString($filepath) {
$out = 'null';
$handle = #fopen($filepath, 'rb');
if ($handle) {
$content = #fread($handle, filesize($filepath));
// bin2hex() PHP Version >= 5.4 Only!
$content = bin2hex($content);
#fclose($handle);
$out = "0x" . $content;
}
return $out;
}
I hope this helps someone.
I have a simple html form, that saves the email message and multiple attachments path. I am saving the files on the server and their path to the database filed.
Now how can i retrive the files from its path, and then show them to user, when click on Download, I am using the following code for getting the file, but this is not working
$query = "
SELECT `type`, `name`, `size`, `file1`,`file2`,`file3`,`file4`,`file5`
FROM `upload` WHERE `id` = {$id}";
$result = $dbLink->query($query);
if($result) {
if($result->num_rows == 1) {
$row = mysqli_fetch_assoc($result);
header("Content-Type: ". $row['type']);
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
$path = $row['file1'];
$dir = opendir($path);
echo $dir;
while ($dir && ($file = readdir($dir)) !== false) {
echo $file;
}
The echoed file doesnot contain any data.
This i am doing now for only one file, whose path is at "file1". Similarly i have 5 attachments path, and i have to retrive them all in this code.
Please how can i do it.
First: You can't have more than one download like this. You can only send that header once and that's it.
Is $path the full path to the file? You could try is_readable($file) to check first in a test. Once you have the full path though, it's simple.
header("Content-Type: application/octet-stream");
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
readfile($row['file1']);
exit();
Readfile outputs directly and streams it, so you don't have to read the content in and then output it. Add the exit to make sure no other output get's added after it, or you could corrupt the file.
This works, assuming $row['file1'] has a correct path!
For multiple files, you have to make multiple calls. Like give the user mutliple links they can click on for downloads.
The only alternative is that you pack it together using zip for example, and send it as one large zipfile.
Im exporting my mysql database to excel, and everything is working, but I want the price field to display with a dollar sign and commas within the excel spreadsheet.
Here is my code:
$pubtable = $_GET["publication"];
$addate = $_GET["adDateHidden"];
$export = mysql_query("SELECT * FROM $pubtable WHERE addate = '$addate' ORDER BY price DESC") or die ("Sql error : " . mysql_error());
$fields = mysql_num_fields($export);
for($i = 0; $i < $fields; $i++){
$header .= mysql_field_name($export , $i). "\t";
}
while($row = mysql_fetch_row($export)){
$line = '';
foreach($row as $value) {
if(!isset($value) || trim($value) == "") {
$value = "\t";
} else {
$value = str_replace('"' , '""' , $value);
$value = '"' . $value . '"' . "\t";
}
$line .= $value;
}
$data .= trim($line). "\n";
}
$data = str_replace("\r" , "" , $data);
if(trim($data) == ""){
$data = "\n(0)Records Found!\n";
}
header("Content-type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=".$pubtable."_".$addate.".xls");
header("Pragma: no-cache");
header("Expires: 0");
header ('Content-Transfer-Encoding: binary');
header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header ('Cache-Control: cache, must-revalidate');
print "$header\n$data";
I tried doing this
$export = mysql_query("SELECT CONCAT('$', FORMAT(price, 2)) as fieldalias * FROM $pubtable WHERE addate = '$addate' ORDER BY fieldalias DESC") or die ("Sql error : " . mysql_error());
this formats it correctly but it only outputs the price field and nothing else.
Technically, you're not producing an Excel spreadsheet. You're producing a CSV file with a .xls extension. CSV has no mechanism for adding formatting, because it's just plain text. You can have MySQL and/or PHP format a number into what looks like a nice currency value, but then you're destroying its existence as a number. It'll be a string-that-used-to-be-a-number.
You should use PHPExcel to produce an ACTUAL Excel file, into which you can add all the usual goodies that Excel supports, including colors and formulae.
Your code is generating a text file (CSV formated) with a XLS extension. Then, under Windows with an Excel installed, it may be automatically opened by Excel despite the content is only text file.
This method cannot produce any data with style.
I suggest that you use OpenTBS to easily build your Excel file. OpenTBS is a PHP class which can build real XLSX, DOCX, ODT, ODS and more... using templates. You just design the template with Excel and then merge it with the data under PHP and you have a new XSLS directly for download, or as a files saved on the server.