An Excel file is stored in a database (hexvalues of former binary data). I need to read it and make it available for download.
Here's the code...
$out = hex2bin($out); // the stuff from the database
header("Content-Type: application/vnd.ms-excel");
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename='$filename'");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
die($out);
Actually I receive stuff... and it looks like the original file with a slight difference.
When using a hex-editor, it shows
ÐÏࡱá
instead of
ÐÏࡱá
(looks like an additional tab). So Excel isn't able to show the sheet but the raw data.
That's not from the data in $out; the conversion bin2hex (during import in database) and hex2bin (export from database) works without problems. If I write $out to a file via fopen / fwrite, it's exactly the original Excel file (which I can open normally).
How can I accomplish this?
Ensure you don't have this extra tab character before the opening <?php tag or after the closing one ?>. Actually, it is good practice to omit the closing tag exactly for this reason.
Related
I am currently working on a utility that pulls files out of an MSSQL database. The body of the files are stored in the database as base64 string which I am decoding with the PHP function base64_decode(). To begin the file to download when the page opens I am using the headers:
$filename = $file[0][0];
$file_body = base64_decode( $file[0][1] );
$size = $file[0][2];
$type = $file[0][3];
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer");
header("Content-Length: $size;");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: $type ");
header("Content-Transfer-Encoding: binary");
echo $file_body;
Files download and everything works perfect until the file size is over about 48kb. After that only 48kb of the file is downloaded. I have tested using many files types and still have the same result. I have boosted php memory and post size in php.ini at the suggestion of other posts I have found online, still no luck.
I realize PHP may not be the best way to accomplish this, however, this is what I have available to me.
Any ideas how I can ensure a complete file is always downloaded?
You don't need to store length (size) anywhere. You should calculate it on the fly in the following way:
$size = strlen($file_body);
...
header("Content-Length: $size;");
I've seen a couple of similar questions but have not had one that answers my issue.
I have an export to CSV button which exports results from my database to CSV.
I don't want to save the file, but I just want to use headers to export the echo content to a file which should then be opened in Excel (or similar product).
All works fine but Excel does not appear to separate the values, but rather shows all rows in 1 row with the commas intact. I found a solution elsewhere where I should add "sep=,\r\n" to the first line to tell Excel to use commas as the delimiter, which then makes it work great; but, in other products it now shows the sep=, on the first line and continues with the remaining of the output.
Here is the code I'm using:
header("Expires: 0");
header("Cache-control: private");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer");
header("Content-Type: application/vnd.ms-excel");
header("Content-disposition: attachment; filename=export.csv");
echo "sep=,\r\n"; // This makes it work in excel but fails in other products such as openoffice
echo "this,is,just,a,test\r\n";
exit;
As Mark Baker suggested, as the dilimeter is set by locale settings, I changed it to ; and it worked like a charm :) Thank you!
i am using php_excel to export to xlsx. In my application im making use of template.
When i download, the xlsx file gets downloaded fine, but when we open its showing the following warning:
"Excel found unreadable content in 'project_report(3).xlsx'. Do you want to recover the contente of this workbook? If you trust the source of this workbook, click Yes."
If i click yes it opens the file correctly.
And one more thing is when i attach the downloaded file to the mail. And if i open it sing Google Spread sheet it says bad format unable to open.
so if anyone know the reason please suggest me to solve this.
check your headers, here are mine:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");;
header("Content-Disposition: attachment;filename=$filename");
header("Content-Transfer-Encoding: binary");
$objWriter->save('php://output');
check for output (spaces before <?php forgotten echo? etc
I want to use the ajax functionality to download whereby the user will click the download link which will (using ajax and $_GET) access a PHP file which will process the sent $_GET variables and access the correct file for downloading.
I have a few PHP scripts to handle the processing of the $_GET variables which work on their own but when accessed using Ajax, they stop working.
The Ajax/PHP code im using is below:
function ajaxDown(){
$('#downloadmsg').html(
'<img src=\"media/images/ajaxloader.gif\" width=\"128\" height=\"15\">');
$('#downloadmsg').load(
'media/downloads/downManager.php?file=".$filequery['filename']."&ftype=".$downex[1]."');
}
Please look through my code and help me find what Im doing wrong.
Thanx
I think the problem is that you're trying to load a file result INTO #downloadmsg, which isn't going to work because .load() is only going to load results as HTML...NOT binary data or other encoding.
One approach that might work is creating a hidden iframe in HTML, like this:
<iframe id="secretIFrame" src="" style="display:none; visibility:hidden;"></iframe>
Then, set the attr of the iframe to your querystring:
$("#secretIFrame").attr("src","myphpscript.php?option1=apple&option2=orange");
and then using PHP headers to force the download when the source is set (here's an example of an exporter header set from one of my scripts that uses an octet stream):
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename=data.xls ");
header("Content-Transfer-Encoding: binary ");
Hope this helps!
I know I'm late! But I think I have a solution that's a little cleaner without the use of a hidden iframe and you won't even need an ajax request to do it! Using PHP Headers as noted in the accepted answer in a download.php file
<?php
//download.php
/*
All your verification code will go here
*/
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename=".$_GET['file']);
header("Content-Transfer-Encoding: binary ");
And on the JS end, simply
function download(filename){
window.location="http://whateveryoursiteis.com/download.php?file="+filename;
}
Works like a charm :O
Normally, when I want to allow a user to download a file without revealing the exact location, I just use something like this to let them download the file:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . $filename) . "\";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filename));
readfile("$filename");
But if they are using a modern browser or other download client, and they pause the download and try to resume it, the script (assuming they are still authenticated or whatever) will resend the headers and the file contents from the beginning, thus breaking the download, and basically requiring the file to be redownloaded from the beginning.
How can I enable my script to compensate for paused (and consequentially, resumed) downloads?
Use php's built-in fopen to open the file and then fseek to the right place (based on the range in the request header) and then return the partial file using fpassthru instead of using readfile.
You can find some example code in php under the comments for fread
You need to read the request headers like Range, If-Range, etc then seek to the correct location in the file. Normally a web-server would do this for you on an ordinary file. It's a bit complex but here's something that might get you started:
http://forums.asp.net/t/1218116.aspx
http://www.notes411.com/dominosource/tips.nsf/0/480C4E3BE825F69D802571BC007D5AC9!opendocument
For the second link the code is in part 12