PHP header() failing in Chrome and Firefox - php

The following code works in Safari but not Firefox or Chrome
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
ob_end_flush();
exit;
The webpage at XXXX might be temporarily down or it may have moved permanently to a new web address.
Error code: ERR_INVALID_RESPONSE
$file variable links to a file outside of the public_html directory.
I can't seem to find a fix, any ideas?

I've had issue with filesize() on chrome and firefox in the past. This was my fix.
<?php
Function real_filesize($file) {
$fmod = filesize($file);
if ($fmod < 0) $fmod += 2.0 * (PHP_INT_MAX + 1);
$i = 0;
$myfile = fopen($file, "r");
while (strlen(fread($myfile, 1)) === 1) {
fseek($myfile, PHP_INT_MAX, SEEK_CUR);
$i++;
}
fclose($myfile);
if ($i % 2 == 1) $i--;
return ((float)($i) * (PHP_INT_MAX + 1)) + $fmod;
}
$filename = "somefile.ext";
$filepath = "some/dir/path/to/file/".$filename;
$filesize = real_filesize($filepath);
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header("Content-Type: application/download");
header("Content-Disposition: attachment; filename=".basename($filename).";");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $filesize);
ob_clean();
flush();
readfile($filepath);
exit();
?>

Just removed the line ob_clean() worked for me.

Related

PHP Can't download over 40MB weight files

I created a simple file to download files.
I have the following code:
function DownloadFile($file) { // $file = include path
if(file_exists($file)) {
header('HTTP/1.0 200 OK', true, 200);
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
ob_clean();
flush();
readfile($file);
exit;
}
}
The problem is if I try to download files over 40-50MB the file is downloaded blank(0KB) but if I try below 40MB it is working perfectly.
What is the problem?
Like explained in this article https://www.sitepoint.com/community/t/php-file-size-download-limit/6541 you need to set
memory_limit = 128M
post_max_size = 300M
in php.ini file
The solution:
function DownloadFile($file) { // $file = include path
if(file_exists($file)) {
header('HTTP/1.0 200 OK', true, 200);
header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
ob_end_flush();
if ($fd = fopen ($file, "r")) {
set_time_limit(0);
ini_set('memory_limit', '1024M');
while(!feof($fd)) {
echo fread($fd, 4096);
flush();
}
}
}
}

readfile() returns empty file while trying to force download

I'm trying to force download of .dwg files with the following code:
$filename = $_GET['f'];
$upload_path = wp_upload_dir();
$src = $upload_path['basedir'] . '/' . $filename;
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);
header("Content-disposition: attachment; filename=\"{$filename}\"");
header("Content-Type: application/octet-stream");
header('Content-Transfer-Encoding: binary');
readfile($src);
die();
The path to the file is correct, but it only returns a file that is 6 byte and that is not possible to open. It should be 754 bytes. Anyone who can help me out here?
//Example file
$src = "/var/www/wp/wp-content/uploads/Glasparti-modell-Silence.dwg";
Try to add the Content-length header :
$size = filesize($src);
header("Content-length: $size");
Try with:
$name = $_GET['f'];
$url = './files/'.$name;
header("Content-type: application/octet-stream");
header("Content-disposition: attachment;filename=$name");
readfile($url);
I solved this by the following in .htaccess instead:
<FilesMatch "\.(dwg)$" >
ForceType application/octet-stream
Header add Content-Disposition "attachment"
</FilesMatch>
Can you please use .dwg file Content-Type:
application/acad
application/x-acad
application/autocad_dwg
image/x-dwg, application/dwg
application/x-dwg
application/x-autocad
image/vnd.dwg
drawing/dwg
header("Content-type: 'application/pdf'");
header("Content-Type: application/force-download");
Can you try this,
<?php
$file = '';// file path here
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}else{
echo "File not found";
}
?>
Try it !!
/**
* file download in MVC
*
* #author VECTOR Ann <ann#vector.cool>
* #since 1.0.1
*
* #param string $file 提供下載的檔案絕對路徑
* #param string $download_name 下載的檔名
* #return void
*/
function v_file_download($file,$download_name=''):void
{
if (is_file($file)) {
if($download_name=='')$download_name = date('Y_m_d',time()).".zip";
header_remove();
ob_end_clean();
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($download_name));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
ob_end_flush();
exit;
}
}

Downloaded file save with 0kb and damaged

I have a problem with download script
when I download any file it is save with 0kb.
Any ideas? Here is my PHP script
<?php
$file = $_GET['fname'];
$fullpath = get_bloginfo('template_url')."/application/display/1358947404.pdf";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fullpath));
header('Expires: 0');
header('Cache-Control: must-revalidate');
ob_clean();
flush();
readfile($fullpath);
?>
Please add content-length header as well .
Please try this:-
<?php
$file = $_GET['fname'];
$fullpath = get_bloginfo('template_url')."/application/display/1358947404.pdf";
$headers = get_headers($fullpath, 1);// use file absolute path here
$fsize = $headers['Content-Length'];
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fullpath));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header("Content-Length: " . $fsize);
ob_clean();
flush();
readfile($fullpath);
?>
Try below code hope it will help you.
I have tested this in my localhost.
$file = $_GET['fname'];
$fullpath = get_bloginfo('template_url')."/application/display/1358947404.pdf";
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fullpath));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($fullpath));
ob_clean();
flush();
readfile($fullpath);

Forcing download in Safari keeps window open

I'm forcing a download on links using this code from the PHP.net site:
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
I put this code in a file called 'download.php', and call it from a page (Click).
It works fine on all browsers, but on Safari the window it opens ('download.php') stays open during and after the download/open process. In other browsers it disappears immediately. Has anyone else come across this problem, and if so are there any suggestions as to how to solve it?
I tried this and it seems to be working equally in all browsers. Try this code, considering that Safari and IE need of more characters as headers to be sent:
#$file = 'load.php';
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
for($i = 0; $i < 40000; $i++) {
echo ' '; // extra spaces
}
flush();
usleep(50000);
exit;

How to determine how many bytes sent over http

I need to know how to determine how many bytes sent over http.
This is what I did so far.
ignore_user_abort(true);
header('Content-Type: application/octet-stream; name="file.pdf"');
header('Content-Disposition: attachment; filename="file.pdf"');
header('Accept-Ranges: bytes');
header('Pragma: no-cache');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-transfer-encoding: binary');
header('Content-length: ' . filesize('file/test.pdf'));
readfile('file/test.pdf');
if (connection_aborted()) {
$transfer_success = false;
$bytes_transferred = ftell($handle);
echo $bytes_transferred;
die();
}
Can anyone help me out ?
Thanks
Take a look at this other post of the same question:
PHP - determine how many bytes sent over http
Code example taken from the linked page (originally posted by J., modified to fit your example):
ignore_user_abort(true);
$file_path = 'file/test.pdf';
$file_name = 'test.pdf';
header('Content-Type: application/octet-stream; name=' . $file_name );
header('Content-Disposition: attachment; filename="' . $file_name . '"');
header('Accept-Ranges: bytes');
header('Pragma: no-cache');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-transfer-encoding: binary');
header('Content-length: ' . $file_path);
$handle = fopen($file_path, 'r');
while ( ! feof($handle)) {
echo fread($handle, 4096);
if (connection_aborted()) {
$transfer_success = false;
$bytes_transferred = ftell($handle);
break;
}
}
fclose($handle);
Try to use the return value of readfile:
$bytes_transferred = readfile('file/test.pdf');
$transfer_success = ($bytes_transfered == filesize('file/test.pdf'));
if (!$transfer_success) {
// download incomplete
}

Categories