|
-
Aug 29th, 2009, 12:59 PM
#1
Thread Starter
Hyperactive Member
[RESOLVED] UTF8 and force download script
I'm using this code to force download files:
Code:
switch( $file_extension )
{
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "rar": $ctype="application/rar"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: $ctype="application/force-download";
}
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers
header("Content-Type: $ctype; charset: UTF-8;");
header("Content-Disposition: attachment; filename=".$ftitle.";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
readfile("$filename");
exit();
$ftitle is utf8 string that is retreived from mysql table, it is may be english, arabic ...etc depend on the filename field stored in that location.
the problem is the name (that appear in save dialog) is ok when it is english, but when it is arabic it is appear with strange chars like ظٹط©
I did try to use utf8_encode($ftitle) but the same problem.
thank's in advance
-
Aug 29th, 2009, 01:02 PM
#2
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
Note: the field ftitle is utf8 encoded in mysql table. and I did use mysql_query('set names utf8'); but the same problem
Last edited by Visual Basic.Net; Aug 30th, 2009 at 08:50 AM.
-
Jan 30th, 2010, 04:09 PM
#3
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
-
Jan 30th, 2010, 07:47 PM
#4
Re: UTF8 and force download script
You're not entitled to a solution.
Anyway, no problems with this working in Firefox. But in IE I see your issue. Some Googling suggests that urlencode() will make IE work... and it does, but then that screws up Firefox. Well based on that, you could do some User Agent sniffing, but that's never a great idea. Let me see if I can't find a better, cross-browser solution...
Btw, I'd also advise putting quotes around filename:
Code:
header("Content-Disposition: attachment; filename=\"".urlencode($ftitle)."\";" );
If you don't have them, some browsers will cut off anything that comes after a whitespace. You may also want the file extension on filename, or the file the user saves won't have one.
Edit: nope, can't find a cross-browser solution; on the contrary I've found evidence suggesting that there isn't an interoperable solution (at this time). But if someone else wants to prove me wrong, I welcome it.
Last edited by SambaNeko; Jan 30th, 2010 at 08:09 PM.
-
Jan 31st, 2010, 03:25 AM
#5
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
Thank's alot SambaNeko, It solved, But another problem appeared!!
when I upload a .rar file, and download it with the above force-download script, the resulted downloaded file is corrupt. while when downloading the same file directly (not through the script) it is downloaded successfully!
That problem appeared only when I tested it on the server, while on localhost, it worked ok!
I tried this http://w-shadow.com/blog/2007/08/12/...load-with-php/
but the same problem, >=1MB rar files are always corrupted!!!
Thank's in advance
-
Feb 2nd, 2010, 06:37 AM
#6
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
if you see the comments in the above URL, there are also some people who have the same problem!
I tried to reduce the chunk size but that dosn't solve the problem 
Thank's in advance
-
Feb 2nd, 2010, 01:10 PM
#7
Re: UTF8 and force download script
In the full script, connection_aborted() is checked while reading the file; my guess is that your remote server is aborting while reading the file, while your localhost is not. You could check this by changing the while loop...
Code:
while(!feof($file) &&
(!connection_aborted()) &&
($bytes_send<$new_length)
)
{
$buffer = fread($file, $chunksize);
print($buffer); //echo($buffer); // is also possible
flush();
$bytes_send += strlen($buffer);
}
...to...
Code:
while(!feof($file) && $bytes_send<$new_length){
if(!connection_aborted()){
$buffer = fread($file, $chunksize);
print($buffer);
flush();
$bytes_send += strlen($buffer);
}else{
die("Connection aborted: ".connection_status());
}
}
If you get the "Connection aborted" message, what number do you get after the colon?
Last edited by SambaNeko; Feb 2nd, 2010 at 01:14 PM.
-
Feb 3rd, 2010, 06:18 AM
#8
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
But how the message will be displayed? as a messagebox or the download dialog will be closed, and the message will be printed in the browser?!
I did change the code and tried to download the rar file again. but nothing happened, no messagebox nor text on the browser. and the downloading completed. The size of the downloaded file is correct 2.10MB. but when I opened the correct file and the corrupted one with a UTF8 text editor and saw that the first line is different, and the rest of the lines are same for some lines at the beginning, but after many lines, they became different again!
Thank's alot SambaNeko
-
Feb 3rd, 2010, 06:24 AM
#9
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
here is the full code I used:
Code:
<? ob_start(); ?>
<?php
session_start();
echo '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >';
error_reporting(0);
if(trim($_SESSION['downloadid'])=="" or (isset($_SESSION['downloadid'])==false)) {
exit;
}
include("dbconnect.php");
$fileid=(int) $_SESSION['downloadid'];
$_SESSION['downloadid']="";
$mysqlresult=mysql_query("select * from file where id=".$fileid) or die("Error");
$rnum = mysql_num_rows($mysqlresult);
if($rnum<=0) {
echo "Not Exists";
exit;
}
$fname = mysql_result($mysqlresult,0,'fname');
$ftitle = mysql_result($mysqlresult,0,'ftitle');
$fsize = mysql_result($mysqlresult,0,'fsize');
$ftype = mysql_result($mysqlresult,0,'ftype');
$filename="./SAVEDFILES/".$fname;
$file_extension = strtolower(substr(strrchr($filename,"."),1));
if ( ! file_exists( $filename ) )
{
exit;
};
$bbb = basename($filename);
$nnn = substr($bbb,0,strpos($bbb,'.'));
$filetts = substr($bbb,strpos($bbb,'.'));
$ffffff = $nnn;
//=======================================================
function output_file($file, $name, $mime_type='')
{
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
$known_mime_types=array(
"pdf" => "application/pdf",
"txt" => "text/plain",
"html" => "text/html",
"htm" => "text/html",
"exe" => "application/octet-stream",
"zip" => "application/zip",
"doc" => "application/msword",
"xls" => "application/vnd.ms-excel",
"ppt" => "application/vnd.ms-powerpoint",
"gif" => "image/gif",
"png" => "image/png",
"jpeg"=> "image/jpg",
"jpg" => "image/jpg",
"php" => "text/plain"
);
if($mime_type==''){
$file_extension = strtolower(substr(strrchr($file,"."),1));
if(array_key_exists($file_extension, $known_mime_types)){
$mime_type=$known_mime_types[$file_extension];
} else {
$mime_type="application/force-download";
};
};
@ob_end_clean();
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
if(isset($_SERVER['HTTP_RANGE']))
{
list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
list($range) = explode(",",$range,2);
list($range, $range_end) = explode("-", $range);
$range=intval($range);
if(!$range_end) {
$range_end=$size-1;
} else {
$range_end=intval($range_end);
}
$new_length = $range_end-$range+1;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range-$range_end/$size");
} else {
$new_length=$size;
header("Content-Length: ".$size);
}
$chunksize = 1*(100*100);
$bytes_send = 0;
if ($file = fopen($file, 'r'))
{
if(isset($_SERVER['HTTP_RANGE']))
fseek($file, $range);
while(!feof($file) && $bytes_send<$new_length){
if(!connection_aborted()){
$buffer = fread($file, $chunksize);
print($buffer);
flush();
$bytes_send += strlen($buffer);
}else{
die("Connection aborted: ".connection_status());
}
}
fclose($file);
} else die('Error - can not open file.');
die();
}
set_time_limit(0);
$file_path=$filename;
output_file($file_path, $ftitle);
?>
<?php ob_flush(); ?>
Thank's in advance
-
Feb 3rd, 2010, 11:55 AM
#10
Re: UTF8 and force download script
you're using fopen() to read; make sure you force fopen to read binary files by appending 'b' to the second parameter (rb, wb, etc). this may or may not be causing you any problems.
anddd, in the future, you should really try indenting. it can get really to read through a complex/long script with no indenting.
-
Feb 3rd, 2010, 06:26 PM
#11
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
Thank's alot kows, finally Solved!!! 
what do you mean by "indenting" ?
last question plz: the downloading dialog box, appeared without progressbar. Just says for example "100Bytes Opened So Far...". I thought that
header("Content-Length: ".$size);
will solve the problem, but it didn't
Thank's alot SambaNeko and kows.
-
Feb 3rd, 2010, 09:44 PM
#12
Re: UTF8 and force download script
you know what an indent is when you're writing a paper or something, correct?
indentation:
PHP Code:
<?php //indented because it's a "level up" from the php tag if( ... condition ...){
//indented because it's a "level up" from the if block
switch( ... ){
case 1: //indented further break;
default: //and again
}
}
//back to first level ?>
this makes things much easier to read. for example:
PHP Code:
<?php //indented because it's a "level up" from the php tag if( ... condition ...){
//indented because it's a "level up" from the if block
switch( ... ){
case 1: //indented further break;
default: //and again
}
}
//back to first level ?>
content-length should provide the browser with the correct size information, as long as your $size variable is not empty.
-
Feb 4th, 2010, 05:20 AM
#13
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
Mr.kows, the first problem dosn't solved 
still some rar files downloaded corruptly through script, while correctly through direct downloading.
I really tired with this code. It taked alot of time 
Here is the full code with intending:
Code:
<? ob_start(); ?>
<?php
session_start();
echo '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >';
error_reporting(0);
if(trim($_SESSION['downloadid'])=="" or (isset($_SESSION['downloadid'])==false)) {
echo "You Can't access this page directly";
exit;
}
include("dbconnect.php");
$fileid=(int) $_SESSION['downloadid'];
$_SESSION['downloadid']="";
$mysqlresult=mysql_query("select * from file where id=".$fileid) or die("Error");
$rnum = mysql_num_rows($mysqlresult);
if($rnum<=0) {
echo "File Dosn't Exists";
exit;
}
$fname = mysql_result($mysqlresult,0,'fname');
$ftitle = mysql_result($mysqlresult,0,'ftitle');
$fsize = mysql_result($mysqlresult,0,'fsize');
$ftype = mysql_result($mysqlresult,0,'ftype');
$filename="./SAVEDFILES/".$fname;
// addition by Jorg Weske
$file_extension = strtolower(substr(strrchr($filename,"."),1));
if ( ! file_exists( $filename ) ){
echo "<html><title>Error</title><body>Error: File Dosn't Exists</body></html>";
exit;
}
$bbb = basename($filename);
$nnn = substr($bbb,0,strpos($bbb,'.'));
$filetts = substr($bbb,strpos($bbb,'.'));
$ffffff = $nnn;
//=======================================================
function output_file($file, $name, $mime_type=''){
if(!is_readable($file)) die('File not found or inaccessible!');
$size = filesize($file);
$name = rawurldecode($name);
$known_mime_types=array(
"pdf" => "application/pdf",
"txt" => "text/plain",
"html" => "text/html",
"htm" => "text/html",
"exe" => "application/octet-stream",
"zip" => "application/zip",
"doc" => "application/msword",
"xls" => "application/vnd.ms-excel",
"ppt" => "application/vnd.ms-powerpoint",
"gif" => "image/gif",
"png" => "image/png",
"jpeg"=> "image/jpg",
"jpg" => "image/jpg",
"php" => "text/plain"
);
if($mime_type==''){
$file_extension = strtolower(substr(strrchr($file,"."),1));
if(array_key_exists($file_extension, $known_mime_types)){
$mime_type=$known_mime_types[$file_extension];
}else{
$mime_type="application/force-download";
}
}
@ob_end_clean(); //turn off output buffering to decrease cpu usage
// required for IE, otherwise Content-Disposition may be ignored
if(ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off');
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="'.$name.'"');
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// multipart-download and download resuming support
if(isset($_SERVER['HTTP_RANGE'])){
list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2);
list($range) = explode(",",$range,2);
list($range, $range_end) = explode("-", $range);
$range=intval($range);
if(!$range_end) {
$range_end=$size-1;
} else {
$range_end=intval($range_end);
}
$new_length = $range_end-$range+1;
header("HTTP/1.1 206 Partial Content");
header("Content-Length: $new_length");
header("Content-Range: bytes $range-$range_end/$size");
} else {
$new_length=$size;
header("Content-Length: ".$size);
}
$chunksize = 1*(10*10); //you may want to change this
$bytes_send = 0;
if ($file = fopen($file, "rb")){
if(isset($_SERVER['HTTP_RANGE'])) fseek($file, $range);
while(!feof($file) && (!connection_aborted()) && ($bytes_send<$new_length)){
$buffer = fread($file, $chunksize);
print($buffer); //echo($buffer); // is also possible
flush();
$bytes_send += strlen($buffer);
}
fclose($file);
} else die('Error - can not open file.');
}
set_time_limit(0);
$file_path=$filename;
output_file($file_path, $ftitle);
?>
<?php ob_flush(); ?>
-
Feb 4th, 2010, 05:41 AM
#14
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
Note:
When I download the file directly from server it opened without any problem.
when I download the file through script it downloaded with the same size but corruptly. I got the following error:
This archive is either in unknown format or damaged. Unexpected end of archive.
That when I opened the rar file directly through Winrar or through 7-Zip. but when I open the file through 7-Zip=>Open Archive ... it opened without any problem!
It seems that the error is at the end of the file?!
how can I solve this problem plz?
Thank's in advance
-
Feb 4th, 2010, 09:51 AM
#15
Re: UTF8 and force download script
I'll try to take a look at this in more detail when I get a chance; that won't be until later tonight. in the meantime, if you would like, this comment on PHP.net looks like a better written version of what you're doing, and may have what you're missing. make a new file, try it out, and try to spot any differences between your script and it if you're simply intent on fixing your own iteration.
-
Feb 4th, 2010, 11:08 AM
#16
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
Thank's alot bro... I replaced the funtion I used with this one:
Code:
function dl_file_resumable($file, $filetitle111,$is_resume=TRUE)
{
if (!is_file($file))
{
die("<b>404 File not found!</b>");
}
//Gather relevent info about file
$size = filesize($file);
$fileinfo = pathinfo($file);
//workaround for IE filename bug with multiple periods / multiple dots in filename
//that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
$filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ?
preg_replace('/\./', '%2e', $filetitle111, substr_count($filetitle111, '.') - 1) :
$filetitle111;
$file_extension = strtolower($path_info['extension']);
//This will set the Content-Type to the appropriate setting for the file
switch($file_extension)
{
case 'exe': $ctype='application/octet-stream'; break;
case 'zip': $ctype='application/zip'; break;
case 'mp3': $ctype='audio/mpeg'; break;
case 'mpg': $ctype='video/mpeg'; break;
case 'avi': $ctype='video/x-msvideo'; break;
default: $ctype='application/force-download';
}
//check if http_range is sent by browser (or download manager)
if($is_resume && isset($_SERVER['HTTP_RANGE']))
{
list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($size_unit == 'bytes')
{
//multiple ranges could be specified at the same time, but for simplicity only serve the first range
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else
{
$range = '';
}
}
else
{
$range = '';
}
//figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);
//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)),($size - 1));
$seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0);
//add headers if resumable
if ($is_resume)
{
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($size - 1))
{
header('HTTP/1.1 206 Partial Content');
}
header('Accept-Ranges: bytes');
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size);
}
//headers for IE Bugs (is this necessary?)
//header("Cache-Control: cache, must-revalidate");
//header("Pragma: public");
header('Content-Type: ' . $ctype);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: '.($seek_end - $seek_start + 1));
//open the file
$fp = fopen($file, 'rb');
//seek to start of missing part
fseek($fp, $seek_start);
//start buffered download
while(!feof($fp))
{
//reset time limit for big files
set_time_limit(0);
print(fread($fp, 1024*8));
flush();
ob_flush();
}
fclose($fp);
exit;
}
The progressbar appeared, but the 1st problem still there, even worse. Files are totally corrupted, and I can't open them even as Archive!
Thank's alot for helping me
-
Feb 8th, 2010, 07:28 AM
#17
Thread Starter
Hyperactive Member
Re: UTF8 and force download script
The problem solved by changing the encoding of the file from UTF-8 to "system default"!!!
Thank's alot for all
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|