Принудительно скачать скрипт - PullRequest
0 голосов
/ 09 октября 2009

Я работал над красивым сценарием «принудительной загрузки файла», цель которого - убедиться, что файлы предлагаются для загрузки, а не отображаются в браузере, независимо от типа файла.

Раньше он работал хорошо, но недавно я получил отзыв, что он не будет работать, особенно для файлов pdf и xls (MS Excel). Файл либо определяется как «недействительный» в случае PDF, либо получает часть страницы каталога html-файлов поверх его содержимого в случае файла xls.

Что именно не так с моей функцией?

Вот оно. Обратите внимание, что он может работать с 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 ]

1 голос
/ 09 октября 2009

Скрипт теперь работает. Я должен был сделать это вызовы 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");
1 голос
/ 09 октября 2009

Заставить загружать файлы, а не просматривать, практически невозможно, независимо от того, как вы их обрабатываете - сторонние компоненты, такие как Adobe PDF Viewer, могут просто заставить вещи игнорировать заголовки Content-Disposition и делать то, что им нравится. Если вы имеете дело с широкой публикой, вы должны согласиться с тем, что пользователи будут принимать данные, а их или их программное обеспечение, а не ваш веб-сайт, будет определять, как они их используют.

0 голосов
/ 09 октября 2009

может стоить рассмотреть альтернативу .htaccess для принудительной загрузки, например:

AddType application/octet-stream csv
AddType application/octet-stream pdf
AddType application/octet-stream xls
0 голосов
/ 09 октября 2009

Я не уверен, поможет ли это вообще, но попробуйте также добавить следующие заголовки:

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

Проблема с MS и PDF (и многими другими) заключается в том, что они вынуждены открываться с помощью программного обеспечения 3PP, например, MS Excel, и игнорируют Content-Disposition.

Если вышеуказанное не работает, пользователям придется щелкнуть правой кнопкой мыши и выбрать Сохранить как; вероятно, не лучшее решение для вашей проблемы.

...