загрузка php файла: странный заголовок http - PullRequest
0 голосов
/ 01 сентября 2009

Я создаю этот php-скрипт, который отображает дочерние папки и файлы данной папки. Файлы должны быть загружены.

Чтобы раскрыть как можно меньше информации, каждый элемент в каталоге представляет собой форму с кнопкой отправки, которая содержит разметку html. Метод отправки - POST.

ЕСЛИ я нажимаю на каталог, он открывает этот каталог и отображает содержимое просто отлично. Если я нажимаю на файл, он показывает приглашение на загрузку, и файл загружается просто отлично. Но после щелчка я вижу такую ​​вещь:

0 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
trailer
<</Size 34>>
startxref
116
%%EOF
HTTP/1.1 200 OK
Date: Mon, 31 Aug 2009 21:01:36 GMT
Server: Apache
X-Powered-By: PHP/5.2.5
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Keep-Alive: timeout=15, max=93
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html

2822
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

, а остальная часть источника HTML-кода отображаемой страницы приведена в списке.

Что здесь происходит?

ОБНОВЛЕНИЕ: мой код принудительной загрузки:

function offerToDownloadFile($filename, $access_type='url') {


// converting url to local path so Apache can find the file.
// force download:
// 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');
    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();
    exit();

}

Ответы [ 2 ]

2 голосов
/ 01 сентября 2009

Судя по всему, ваш скрипт загрузки файла может задавать неправильную Content-Length, так что последние несколько байтов файла могут перетекать в следующий запрос, вызывая все возможные ошибки.

Какой веб-сервер и ОС вы используете и как вы вызываете PHP? Потому что если бы это была Windows, у меня было бы подозрение, что ваша установка PHP может каким-то образом записывать в стандартный вывод в виде текста, а не двоичного потока. Это приведет к тому, что каждый \ n байт будет преобразован в последовательность \ r \ n, что, вероятно, сделает большинство двоичных файлов нечитаемыми, а также сделает тело ответа немного длиннее, чем заголовок Content-Length.

$ parsed_url ['localpath'] = LOCALROOT. $ Parsed_url [ 'путь'];

Это кажется довольно опасным. Я надеюсь, что $ filename были проверены и проверены с точностью до дюйма, прежде чем пытаться что-то подобное. (Проверка имени файла обманчиво сложна.)

0 голосов
/ 01 сентября 2009

Я не могу сказать вам, что там за весь мусор, но чтобы избежать этого, после того, как вы отправите файл, позвоните die().

...