为什么我下载的文件总是损坏或损坏?

2022-01-02 00:00:00 file download php

我的下载脚本有一个很奇怪的问题

I have a very weird problem with my download script

基本上是

1. 使用GET"获取文件 ID;方法

1.gets a file id with "GET" method

2.从数据库中获取该文件的名称和位置

2.gets the name and location of that file from database

3.将它与标头和读取文件一起发送给客户端

3.sends it to the client with the headers and readfile

但奇怪的是,该文件总是以损坏或损坏的形式出现

but strangely that file always comes out as corrupted or damaged

就像是 zip 或 rar 文件文件大小合适,打开正常

like if it's a zip or rar file file size is right and it opens ok

但是我无法打开其中的压缩文件,这就是我收到文件损坏错误的时候

but i cant open compressed files inside of it and that's when i get the file damaged error

这很奇怪,因为如果代码有问题,我什至不能打开 zip 文件(或者至少我认为我不应该打开)

which is weird cuz if the code had a problem i shouldn't even be able to open the zip file(or at least i think i shouldn't)

另一件事是我在发送标头之前打印了文件及其路径,以确保一切正常

another thing is i've printed out the file with it's path right before sending the headers just to be sure everything is ok

我已经把文件地址放在url上并下载文件,文件没问题,没有错误

I've put the file address on the url and download the file , file was ok with no errors

所以在发送标头之前一切都很好

so everything is fine before sending the headers

这是我的代码

        $file_id = isset($_GET['id']) && (int)$_GET['id'] != 0 ? (int)$_GET['id'] : exit;
        
        
        //////// finging file info
        $file = comon::get_all_by_condition('files' , 'id' , $file_id );
        if(!$file) exit;
        foreach($file as $file){
        $location = $file['location'];
        $filename = $file['file_name'];
        }
        /////////////


        $site = comon::get_site_domian();
        
        $ext = trim(end(explode('.' , $filename )));
        $abslout_path = 'http://'.$site.'/'.$location.'/'.$filename;
        $relative = $location.'/'.$filename;
        

    
    ////////////////// content type 
            switch($ext) {
            case 'txt':
                $cType = 'text/plain'; 
            break;              
            case 'pdf':
                $cType = 'application/pdf'; 
            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';
            break;
        }
   //////////////// just checking 

   if(!file_exists($relative)){
        echo $relative;
        echo '<br />';
        exit;
        }
    
    if( !is_readable( $relative ) )
    exit('its not redable');
    


    if( headers_sent() )
    exit('headers ? already sent !! ');
        

    
    header( 'Pragma: public' ); 
    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-Description:File Transfer' );
    header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
    header( 'Content-Type:'.$cType);
    header( 'Content-Disposition: attachment; filename="'. basename($filename) . '";' );
    header( 'Content-Transfer-Encoding: binary' );
    header( 'Content-Length: ' . filesize($relative) );
    readfile($abslout_path);
    exit;

我已经检查了几次标题,它们很好(我认为),我还添加了人类已知的每个标题,只是为了确定!

I've checked the headers couple times and they are fine(i think) , I've also add every headers known to man just to be sure !

我开始认为这可能不是脚本像字符编码或文件夹权限!或者类似的东西!!

I'm starting to think maybe it's something other than script like char encoding or folder permission ! or something like that !!

我错过了什么吗?

推荐答案

这似乎是为了强制下载而分配的代码,这是我一直使用的一个很好的功能.它也可以处理超过 2GB 的文件.

That seems allot of code just to force-download, here is a nice function I use all the time. It will handle files over 2GB too.

<?php 
$file_id = (isset($_GET['id']) && (int)$_GET['id'] != 0) ? (int)$_GET['id'] : exit;

/*finding file info*/
$file = comon::get_all_by_condition('files', 'id', $file_id);
$path = $file['location'] . '/' . $file['file_name'];

if (!is_file($path)) {
    echo 'File not found.('.$path.')';
} elseif (is_dir($path)) {
    echo 'Cannot download folder.';
} else {
    send_download($path);
}

return;

//The function with example headers
function send_download($file) {
    $basename = basename($file);
    $length   = sprintf("%u", filesize($file));

    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . $basename . '"');
    header('Content-Transfer-Encoding: binary');
    header('Connection: Keep-Alive');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . $length);

    set_time_limit(0);
    readfile($file);
}
?>

相关文章