Trying to download Blob via PHP / MySQL - php

This is one I just can't figure out: I have successfully built an upload feature on a web page to upload files to a MySQL Database. When I go on the server and open them via phpMyAdmin, they all look fine... txt, jpg, pdf, etc.
Yet, after putting together THIS thing (below) to download it, I get a strange problem: All of the text documents (and all other types of files, after I change the extension to 'txt') contain HTML code of the page itself, followed by the original content!
Also, different browsers display differently after the POST. When trying to download a txt file, IE will show the correct data in the ECHO on the page itself (no downloading) with an error message just before it:
Warning: Header may not contain more than a single header, new line detected. in C:\wamp\www\ace\dmain.php on line 82.
Line 82 is 'header("Content-length...'
Neither Firefox nor Chrome show anything. They just allow me to download it.
Here's the code:
<?php
if (isset($_POST['downloadid'])) {
$fileid = $_POST['downloadid'];
try {
$sql = "SELECT * FROM `datastore` WHERE `id` = '".$fileid."'";
$results = $pdo->query($sql);echo $sql;
while ($row = $results->fetch()) {
$filename = $row['filename'];
$mimetype = $row['mimetype'];
$filedata = $row['filedata'];
header("Content-length: strlen($filedata)");
header("Content-type: $mimetype");
header("Content-disposition: download; filename=$filename"); //disposition of download forces a download
echo $filedata;
// die();
} //of While
} //try
catch (PDOException $e) {
$error = '<br>Database ERROR fetching requested file.';
echo $error;
die();
} //catch
} //isset
?>

This:
header("Content-length: strlen($filedata)");
Is not going to produce what you expect. If you look at the headers in wireshark, or another method to view the request you will see that it does not contain an integer.
Use this instead:
header("Content-length: ".strlen($filedata));

After agonizing over fixing it in-place (that is, on the same page with the rest of the html and code), I decided to move it to a dedicated PHP page. After that, it worked fine.
Thanks for the comments!

here is good example and complete source

Related

How would I download blob files (.txt/pdf) from a MySQL database [duplicate]

This is one I just can't figure out: I have successfully built an upload feature on a web page to upload files to a MySQL Database. When I go on the server and open them via phpMyAdmin, they all look fine... txt, jpg, pdf, etc.
Yet, after putting together THIS thing (below) to download it, I get a strange problem: All of the text documents (and all other types of files, after I change the extension to 'txt') contain HTML code of the page itself, followed by the original content!
Also, different browsers display differently after the POST. When trying to download a txt file, IE will show the correct data in the ECHO on the page itself (no downloading) with an error message just before it:
Warning: Header may not contain more than a single header, new line detected. in C:\wamp\www\ace\dmain.php on line 82.
Line 82 is 'header("Content-length...'
Neither Firefox nor Chrome show anything. They just allow me to download it.
Here's the code:
<?php
if (isset($_POST['downloadid'])) {
$fileid = $_POST['downloadid'];
try {
$sql = "SELECT * FROM `datastore` WHERE `id` = '".$fileid."'";
$results = $pdo->query($sql);echo $sql;
while ($row = $results->fetch()) {
$filename = $row['filename'];
$mimetype = $row['mimetype'];
$filedata = $row['filedata'];
header("Content-length: strlen($filedata)");
header("Content-type: $mimetype");
header("Content-disposition: download; filename=$filename"); //disposition of download forces a download
echo $filedata;
// die();
} //of While
} //try
catch (PDOException $e) {
$error = '<br>Database ERROR fetching requested file.';
echo $error;
die();
} //catch
} //isset
?>
This:
header("Content-length: strlen($filedata)");
Is not going to produce what you expect. If you look at the headers in wireshark, or another method to view the request you will see that it does not contain an integer.
Use this instead:
header("Content-length: ".strlen($filedata));
After agonizing over fixing it in-place (that is, on the same page with the rest of the html and code), I decided to move it to a dedicated PHP page. After that, it worked fine.
Thanks for the comments!
here is good example and complete source

Android: Images not downloading from server

I have uploaded few images on my server which will be downloaded to my android application by passing a url. I have written a php file which displays the image. I pass the URL to my android application like this :
'http://myURL/getImage.php?image=logo.png'.
When I copy paste the URL directly in browser the image is displayed correctly.
However the image file is not getting downloaded on my android application. I know that android code is correct because when I am giving any other random image URL the image is downloading correctly. Do I have to give something else in my php file to make the image 'downloadable'.
Image.php
<?php
echo '<img src="Images/'.$_REQUEST['image'].'"/><br />';
?>
It seems you want the PHP to output the image directly. Instead, your code is generating an HTML with the image on it. Although your browser displays similar results, the underlying content is different.
What you actually need could be this:
<?php
$filepath = 'Images/'.$_REQUEST['image'];
$filename = basename($filepath);
$ctype = 'image/jpeg'; // assuming it is a .jpg file
if (is_file($filepath)) {
header('Content-Type: '.$ctype);
header('Content-Length: ' . filesize($filepath));
header('Content-Disposition: attachment; filename="'.$fileName.'"');
echo file_get_contents($file);
exit();
} else {
header("HTTP/1.0 404 Not Found");
// you may add some other message here
exit();
}
This is vulnerable to hazardous $_REQUEST['image'] input. Just filter it somehow. Also you must generate the correct $ctype for the image file.

PHP, MySQL - Trouble downloading uploaded file from database

I have a problem when downloading a file previously uploaded into database, instead of downloading said file the computer downloads a 'download.php' file which is the script to download. I am using some kind of identifier like 'download.php?id=1' to pick and download specific file, and yes, I am aware this code is probably deprecated and not secure.
This is download.php I type:
<?php
session_start();
include("connect.php");
$namatemp=$_SESSION['nama'];
$nistemp=$_SESSION['nislogin'];
$kelastemp=$_SESSION['kelas'];
$mapeltemp=$_SESSION['mapeltemp'];
$chapteridtemp=$_SESSION['chapteridtemp'];
$query=("SELECT mime, name, size, data FROM file WHERE uploader='$namatemp' AND chapter='$chapteridtemp')");
$result=mysql_query($query);
$row=mysql_fetch_array($result);
if($row=1) {
header('Content-Type: '.$row['mime']);
header('Content-Length: '.$row['size']);
header('Content-Disposition: attachment; filename='.$row['name']);
echo $row['name'];
} else {
echo "You have not uploaded such file.";
}
?>
You might want to add:
readfile($row['name']);
Yet I think you better check in that page is the file exist to redirect to a download page and if it does not exist, printing the error, because I'm not so sure if the headers can be nested in an if statement. Of course, I might be wrong and get downvoted for saying this.

Uploaded medium blob truncated on download

I upload a blob to my sql database table with a field that is defined to be of size medium blob. The blob is actually a pdf file of size 4.3mb. The file is uploaded via ftp. After upload, some php code inserts it into the database. I've checked the file within the ftp folder and I can view it correctly. I've checked the file (blob) within the database and I can view it correctly. Both sizes show 4.3mb. If I try to download the file using some code provided by another programmer (below), the file is truncated at about 300kb.
if (!($dbLink = mysql_pconnect($db_server,$db_id,$db_pwd)))
{
print("Failed to connect to database!<BR>\n");
exit();
}
if(!mysql_select_db($db_name,$dbLink))
{
print("Cannot use the database!<BR>\n");
exit();
}
$query = "SELECT name, type, content FROM table_name WHERE link_id = '" . $id . "'";
$result = mysql_query($query, $dbLink) or die('Error, query failed');
list($name, $type, $content) = mysql_fetch_array($result);
//header("Content-length: $size");
header("Content-type: $type");
header("Content-Disposition: attachment; filename=$name");
echo $content;
exit;
I checked my maximum packet size within MySQL and it appears to be about 256mb. My php.ini shows 10mb for posts. I'm at a loss as to why the file is truncated. Can someone please point me in the right direction to solve this?
The PDO interface between PHP and MySQL offers a streaming scheme for LOB-handling. Seeing as how the mysql_ interface was abandoned years ago by its developers, it might be worth trying this.
See this: http://www.php.net/manual/en/pdo.lobs.php
You might consider using code like this.
$db = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'username', 'password');
$query = "SELECT name,
type,
OCTET_LENGTH(content) AS length,
content
FROM table_name
WHERE link_id = :link_id
LIMIT 1";
$stmt = $db->prepare($query);
$stmt->execute(array(":link_id" => $id));
$stmt->bindColumn(1, $name);
$stmt->bindColumn(2, $type);
$stmt->bindColumn(3, $length);
$stmt->bindColumn(4, $data, PDO::PARAM_LOB); /* binds as a stream */
if ($stmt->fetch(PDO::FETCH_BOUND)) {
header("Content-Type: $type");
header("Content-Length: $length");
header("Content-Disposition: attachment; filename=$name");
fpassthru($data);
}
Sorry to say I haven't debugged this. But it's a fairly common use case.
I have resolved this with a different methodology. No matter what I tried from several different examples, I could not get the suggested PHP code to stop truncating files. I stopped storing the file as an attachment in the database, and, simply stored it in a separate folder on the server. The database was updated to insert a "path" link for the file. I changed the php code to:
// Construct an HTTP header that will force the browser to display/download the file.
header("Location: ".$location);
ob_flush();
exit;
This forced a relocation to the actual file stored on the server. The file now opens in the browser. Note: I also had to change some html code to force the file to open in a new tab in the browser.

Export mySQL to excel or csv

I'm no php expert (a mere beginner) but need some help!
After hours searching Google and trying out about 100 different scripts, I finally found one that does what I need - almost.
Basically, my site has a button marked 'Export to Excel'. Visitor to site clicks button and a download begins containing all data from a specified table.
I found this on here - PHP code to convert a MySQL query to CSV
which does exactly what I want except the user sees the following error when trying to open the file:
Error - 'The file you are trying to open, 'export.xls', is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Wo you want to open the file now?'
User clicks 'Yes' and file opens with all data! Brilliant! Except users will not open the file with this error.
I would be very grateful if someone knows a way to fix this.
Many thanks
TT
Or, you could just change the script in the above solution to return a file with the .csv extension. .csv files are associated with Excel, so they should open directly.
Ok, this results from a feature specified by Excel 2007 called Extension Hardening. You can turn it off, but that can only be done client-side. If you click "OK" or "Yes" the file should open anyway. Check this blog post for more info.
EDIT: What this means is that Excel is finding that the file is of a different type (say HTML or CSV) that what is specified by the file extension. Therefore Excel wants to warn you that this file is not what it says it is. Unless you are going to create native Excel files on the server then prompt the user to download them, there is no getting around this error except for each user to turn off Extension Hardening on their own computer.
if you make the first letters “ID” of a text file Excel incorrectly
assumes you are trying to open an SYLK file.
Meaning if the first row & column value is "ID", Excel will throw this warning. Just change it from "ID" to anything else.
Credit: http://alunr.com/excel-csv-import-returns-an-sylk-file-format-error/
Dim objXL As Excel.Application
Dim objWkb As Excel.Workbook
Set objXL = New Excel.Application
'turn off excel warnings
objXL.DisplayAlerts = False
'Open the Workbook
Set objWkb = objXL.Workbooks.Open(fpath)
functions sendFile($filename,$content_type="application/ms-excel") {
header('Content-type: '.$content_type);
header('Content-disposition: Attachment; filename=' . $filename);
readfile($filename);
}
I had the same problem so I looked at the following link: PHP code to convert a MySQL query to CSV
I modified one of the answers to get the headers to work.
include('DBFILE.PHP');
$select="SELECT * FROM SOMETable";
$result = mysqli_query($conn, $select);
if (!$result) die('Couldn\'t fetch records');
$num_fields = mysql_num_fields($result);
//This is what I changed...
$headers ="";
while ($property = mysqli_fetch_field($result)) {
$headers.= $property->name.",";
}
$headers.="\n";
//////
$fp = fopen('php://output', 'w');
if ($fp && $result) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export.csv"');
header('Pragma: no-cache');
header('Expires: 0');
fputcsv($fp, $headers);
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
die;
}
I Tested this and it works like a charm, you just need to add your db connection or include the db.php file that you have.
you can change the name of the file if you edit the following line
header('Content-Disposition: attachment; filename="export.csv"');
Change export to what ever name you like.

Categories