强制下载脚本

时间:2009-10-09 08:00:52

标签: php apache excel download apache2

我开发了一个很好的“强制下载文件”脚本,其目的是确保提供下载文件而不是在浏览器中显示,无论文件类型是什么。

它曾经运作良好,但最近我收到反馈,它不起作用,特别是对于pdf和xls文件(MS Excel)。在PDF的情况下,该文件被检测为“无效”,或者在xls文件的情况下,该文件在其内容之上获取部分html文件目录页。

我的功能究竟出了什么问题?

在这里。请注意,它可以使用URL或本地路径。

    function offerToDownloadFile($filename, $access_type='url') {
    /*
    PHP FORCE DOWNLOAD SCRIPT
    */

    // required for IE, otherwise Content-disposition is ignored
        if (ini_get('zlib.output_compression'))
            ini_set('zlib.output_compression', 'Off');

        if($access_type === 'url') {
        // access type is via the file 's url
            $parsed_url = parse_url($filename);
            $fileinfo = pathinfo($filename);
            $parsed_url['extension'] = $fileinfo['extension'];
            $parsed_url['filename'] = $fileinfo['basename'];
            $parsed_url['localpath'] = LOCALROOT . $parsed_url['path'];
        }
        else {
        // access type is the local file path
            $fileinfo = pathinfo($filename);
            $parsed_url['localpath'] = $filename;
            $parsed_url['filename'] = basename($filename);
            $parsed_url['extension'] = $fileinfo['extension'];
        }


        // just in case there is a double slash created when joining document_root and path
        $parsed_url['localpath'] = preg_replace('/\/\//', '/', $parsed_url['localpath']);

        if (!file_exists($parsed_url['localpath'])) {
            die('File not found: ' . $parsed_url['localpath']);
        }
        $allowed_ext = array('ics','pdf', 'png', 'jpg', 'jpeg', 'zip', 'doc', 'xls', 'gif', 'exe', 'ppt','ai','psd','odt');
        if (!in_array($parsed_url['extension'], $allowed_ext)) {
            die('This file type is forbidden.');
        }

        switch ($parsed_url['extension']) {
            case "ics": $ctype="text/calendar";
                break;
            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";
        }
        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");
        header("Content-Disposition: attachment; filename=\"" . $parsed_url['filename'] . "\";");
        header("Content-Transfer-Encoding: binary");
        //  header("Content-Length: " . filesize($parsed_url['localpath']));
        readfile($parsed_url['localpath']);
        clearstatcache();
        die();
        exit();
    }

4 个答案:

答案 0 :(得分:1)

强制下载文件而不是查看文件几乎无法实现,无论你如何处理它 - 像Adobe的PDF Viewer这样的第三方组件只能强迫事物忽略Content-Disposition标题并做它喜欢的事情。如果您与公众打交道,您必须接受用户将获取数据,而他们或他们的软件不会决定他们如何使用这些数据。

答案 1 :(得分:1)

该脚本现在可以使用了。我不得不改为使用此header()调用。我真的不知道为什么,这是试验和错误导致我找到这个解决方案。

header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"" . $parsed_url['filename'] . "\";");
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");

答案 2 :(得分:0)

我不确定这是否会有所帮助,但也尝试放下以下标题:

header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");

MS和PDF(以及许多其他人)的问题是它们被迫用3PP软件打开,例如MS Excel,并且忽略了内容处置。

如果以上操作不起作用,用户必须右键单击并选择另存为;可能不是解决问题的最佳方案。

答案 3 :(得分:0)

可能值得考虑强制下载的.htaccess替代方案,例如:

AddType application/octet-stream csv
AddType application/octet-stream pdf
AddType application/octet-stream xls