简体   繁体   中英

php download fails on large files

I'm trying to get a link to download files without redirecting, or using another file to download large zip files.

It works great for files under ~100mb, but anything larger and it's sent to an error page in chrome that says: Error code: ERR_INVALID_RESPONSE .

The $file and $path are put into a form with jQuery, and then $('form').submit(); is called.

function downloadFile($file, $path){

        set_time_limit(0);
        $fullPath = $path . $file;

        if ($fd = fopen ($fullPath, "r")) {


            $fsize = filesize($fullPath);
            $path_parts = pathinfo($fullPath);



            $ext = strtolower($path_parts["extension"]);
            switch ($ext) {
                case "pdf":
                header("Content-type: application/pdf"); // add here more headers for diff. extensions
                header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
                break;
                default;
                header("Content-type: application/octet-stream");
                header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
            }
            header("Content-length: $fsize");
            header("Cache-control: private"); //use this to open files directly
            while(!feof($fd)) {
                $buffer = fread($fd, 2048);
                echo $buffer;
            }
        }
        fclose ($fd);
        exit;
    }

Any ideas why it fails on larger files?

Update: When I use the following code, it downloads the file, but the finished file doesn't open as it's corrupted for some reason:

set_time_limit(0);
ini_set('memory_limit', '1024M');
// http headers for downloads
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$file_size);
ob_end_flush();
@readfile($fileinfo['path']);   

When I use this code, it only downloads the first 49.7kb then says it's finished, I even tried ob_flush() and flush() together:

    // http headers for downloads
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"".$filename."\"");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($fileinfo['path']));

    if ($fd = fopen ($fileinfo['path'], "r")) {

            set_time_limit(0);
            ini_set('memory_limit', '1024M');

        while(!feof($fd)) {
            echo fread($fd, 4096);
            flush();
        }   

    }

The only thing I do different in my downloader is Content-Transfer-Encoding: chunked . Also take the flush() out of the loop and make sure you do ob_clean(); flush(); ob_clean(); flush(); before and ob_end_flush(); after sending the data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM