Home » Php » PHP Force Download Causing 0 Byte Files

PHP Force Download Causing 0 Byte Files

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m trying to force download files from my web server using PHP.
I’m not a pro in PHP but I just can’t seem to get around the problem of files downloading in 0 bytes in size.

CODE:

$filename = "FILENAME...";

header("Content-type: $type");
header("Content-Disposition: attachment;filename=$filename");
header("Content-Transfer-Encoding: binary");
header('Pragma: no-cache');
header('Expires: 0');
set_time_limit(0);
readfile($file);

Can anybody help?
Thanks.

How to&Answers:

You’re not checking that the file exists. Try using this:

$file = 'monkey.gif';

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;
}else
{
    echo "File does not exists";
}

And see what you get.


You should also note that this forces a download as an octet stream, a plain binary file. Some browsers will struggle to understand the exact type of the file. If, for example, you send a GIF with a header of Content-Type: application/octet-stream, then the browser may not treat it like a GIF image. You should add in specific checks to determine what the content type of the file is, and send an appropriate Content-Type header.

Answer:

You need to specify the Content-Length header:

header("Content-Length: " . filesize($filename));

Also, you shouldn’t send a Content-Transfer-Encoding header. Both of the HTTP/1.0 and HTTP/1.1 specs state that “HTTP does not use the Content-Transfer-Encoding (CTE) field of RFC 1521”.

Answer:

I use the following method in phunction and I haven’t had any issues with it so far:

function Download($path, $speed = null)
{
    if (is_file($path) === true)
    {
        $file = @fopen($path, 'rb');
        $speed = (isset($speed) === true) ? round($speed * 1024) : 524288;

        if (is_resource($file) === true)
        {
            set_time_limit(0);
            ignore_user_abort(false);

            while (ob_get_level() > 0)
            {
                ob_end_clean();
            }

            header('Expires: 0');
            header('Pragma: public');
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Content-Type: application/octet-stream');
            header('Content-Length: ' . sprintf('%u', filesize($path)));
            header('Content-Disposition: attachment; filename="' . basename($path) . '"');
            header('Content-Transfer-Encoding: binary');

            while (feof($file) !== true)
            {
                echo fread($file, $speed);

                while (ob_get_level() > 0)
                {
                    ob_end_flush();
                }

                flush();
                sleep(1);
            }

            fclose($file);
        }

        exit();
    }

    return false;
}

You can try it simply by doing:

Download('/path/to/file.ext');

Answer:

This problem as same as my website project. This code I’ve used:

<?php

$file = $_SERVER["DOCUMENT_ROOT"].'/.../.../'.$_GET['file'];

 if(!file)
 {
     // File doesn't exist, output error
     die('file not found');
 }
 else
 {

    //$file_extension = strtolower(substr(strrchr($file,"."),1));
    $file_extension = end(explode(".", $file));

    switch( $fileExtension)
    {
    case "pdf": $ctype="application/pdf"; break;
    case "exe": $ctype="application/octet-stream"; break;
    case "zip": $ctype="application/zip"; 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";
    }

    nocache_headers();

     // Set headers
    header("Pragma: public"); // required
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public"); // required for certain browsers
    header("Content-Description: File Transfer");
    header("Content-Type: $ctype");
    header("Content-Disposition: attachment; filename=".$file.";" );
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($file));

     readfile($file);
 }
 ?>

I think the problem is on the server setting like PHP setting or cache setting, but I don’t have any idea to do this my opinion.

Answer:

i am doing this to download a PDF …

$filename = 'Application.pdf';
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=$filename");
echo $pdf;

i think you are missing the last row, where you actually send the file contents of whatever you have in $file.

Pablo

Answer:

The file opened ok for me when I changed the directory to the file location.

$reportLocation = REPORTSLOCATION;

$curDir = getcwd();

chdir($reportLocation);

if (file_exists($filename)) {

    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Length: ' . filesize($filename));
    header('Content-Transfer-Encoding: binary');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');

    ob_clean();
    flush();

    readfile($filename);
}
chdir($curDir);

Answer:

The trick is to check with file_exists to confirm the correct path.
The big confusion is that for PHP paths you don’t need to start with ‘/’ to say your website start path.

 '/folder/file.ext'  #bad, needs to know the real full path

in php / is the website main path already, you don’t need to mention it. Just:

 'folder/file.ext'   #relative to the / website

This will work with file_exists, header filename, readfile, etc…

Answer:

if script work work for small files but for huge files return 0 byte file. you must increate memory_limit via php.ini
also you can add the following line before your code

ini_set('memory_limit','-1');