PHP - 文件流问题

发布于 2024-10-10 09:45:40 字数 594 浏览 2 评论 0原文

我有一个包含下载部分的网站。我需要匿名用户不能直接访问这些文件,因此我将它们放在用户无法访问但 Web 服务器可以访问的目录中。当用户单击链接下载文件时,我需要它重定向到下载页面,该页面会将文件流式传输给用户,而无需用户知道目录或文件的位置,并且会要求他将其保存到自己的计算机上。我在上一篇文章中找到了以下代码,但我无法让它正常工作。可能是我不知道它想要传递给它的变量的正确名称。请附上如何使用您的代码的说明。

$filename='Firefox%20Setup%203.6.13.exe';
$file_path='http://ftp.byfly.by/pub/mozilla.org/firefox/releases/3.6.13/win32/fr';
$file= $file_path."/".$filename;
$len=filesize($file);
header("content-type: application/save");
header("content-length: $len");
header("content-disposition: attachment; filename=$filename");
$fp=fopen($file, "r");
fpassthru($fp);

I have a website that has a downloads section. I need for the files not to be accessed directly by an annonymous user, so I am putting them in a directory not accessable to users, but is accessible to the web server. When the user clicks the link to download the file, I need it to redirect to a download page that will stream the file to the user without him knowing the location of the directory or the file and it will ask him to save it to his computer. I found the following code on a previous post, but I can't get it to work correctly. Could be that I don't know the correct names of the variables that it wants to be passed to it. Please include an explanation of how to use your code.

$filename='Firefox%20Setup%203.6.13.exe';
$file_path='http://ftp.byfly.by/pub/mozilla.org/firefox/releases/3.6.13/win32/fr';
$file= $file_path."/".$filename;
$len=filesize($file);
header("content-type: application/save");
header("content-length: $len");
header("content-disposition: attachment; filename=$filename");
$fp=fopen($file, "r");
fpassthru($fp);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞旧 2024-10-17 09:45:40

我就是这样做的。

<?php

function getFile($file_location) {
    header('Content-Description: File Transfer');
    header('Content-type: application/exe');
    header('Content-Disposition: attachment; filename="supercoolFF.exe"');
    header('Content-Transfer-Encoding: binary');
    ob_end_clean();
    $url_info = parse_url($file_location);
    if (!isset($url_info['query'])) $url_info['query'] = '';
    $http = fsockopen($url_info['host'],$url_info['port']);
    $req = "GET " . $url_info['path'] . "?" . $url_info['query'] . " HTTP/1.1\r\n";
    $req .= "Host: " . $url_info['host'] . ":" . $url_info['port'] . "\r\n";
    $req .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
    $req .= "User-Agent  Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8\r\n";
    $req .= "Accept-Language: en-us,en;q=0.5\r\n";
    $req .= "Accept-Encoding: gzip,deflate\r\n";
    $req .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
    if ($len = strlen($url_info['query']) {
        $req .= 'Content-Length: ' . $len . "\r\n";
        $req .= "Connection: Close\r\n\r\n";
        $req .= $query . "\r\n\r\n";
    } else {
        $req .= "Connection: Keep-Alive\r\n\r\n";
    }
    fputs($http, $req);

    $content = "";
    $content_encountered = FALSE;
    ob_end_clean();
    while(strlen($part = fgets($http, 4096))) {
        if ($content_encountered) {
            echo $part;
            $content .= $part; 
        }
        if ($part == "\r\n") {
            $content_encountered = TRUE;
        }
    }
    fclose($http);
    exit;
}

$filename='Firefox%20Setup%203.6.13.exe?';
$file_path='http://ftp.byfly.by:80/pub/mozilla.org/firefox/releases/3.6.13/win32/fr';

getFile($file_path . '/' . $filename);

当然,最好先执行 HEAD 请求来获取文件大小并在响应中包含 Content-Length 标头,以便用户可以了解需要多长时间。或者,如果您始终要提供相同的文件,则可以对该数字进行硬编码。

This is how I would do it.

<?php

function getFile($file_location) {
    header('Content-Description: File Transfer');
    header('Content-type: application/exe');
    header('Content-Disposition: attachment; filename="supercoolFF.exe"');
    header('Content-Transfer-Encoding: binary');
    ob_end_clean();
    $url_info = parse_url($file_location);
    if (!isset($url_info['query'])) $url_info['query'] = '';
    $http = fsockopen($url_info['host'],$url_info['port']);
    $req = "GET " . $url_info['path'] . "?" . $url_info['query'] . " HTTP/1.1\r\n";
    $req .= "Host: " . $url_info['host'] . ":" . $url_info['port'] . "\r\n";
    $req .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
    $req .= "User-Agent  Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8\r\n";
    $req .= "Accept-Language: en-us,en;q=0.5\r\n";
    $req .= "Accept-Encoding: gzip,deflate\r\n";
    $req .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
    if ($len = strlen($url_info['query']) {
        $req .= 'Content-Length: ' . $len . "\r\n";
        $req .= "Connection: Close\r\n\r\n";
        $req .= $query . "\r\n\r\n";
    } else {
        $req .= "Connection: Keep-Alive\r\n\r\n";
    }
    fputs($http, $req);

    $content = "";
    $content_encountered = FALSE;
    ob_end_clean();
    while(strlen($part = fgets($http, 4096))) {
        if ($content_encountered) {
            echo $part;
            $content .= $part; 
        }
        if ($part == "\r\n") {
            $content_encountered = TRUE;
        }
    }
    fclose($http);
    exit;
}

$filename='Firefox%20Setup%203.6.13.exe?';
$file_path='http://ftp.byfly.by:80/pub/mozilla.org/firefox/releases/3.6.13/win32/fr';

getFile($file_path . '/' . $filename);

Of course, it would be better to do a HEAD request first to get the filesize and include a Content-Length header in the response so the user can have some idea about how long it is going to take. Or, you can hardcode that number, if you are always going to be serving up the same file.

我的痛♀有谁懂 2024-10-17 09:45:40

假设您的目录中有一个名为“hiddenaccess”的文件,文件名为“test.mp3”,您可以在 php 变量中加载路径并让它进行下载

<?php
$file = "./hiddenaccess/test.mp3";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");             
header("Content-Length: " . filesize($file));

@readfile($file);

?>

注意:此文件中没有任何其他 echo 或 print 语句。

Let's say you have a file in a directory called "hiddenaccess" and the file name is "test.mp3" you can load the path in php variable and let it for download

<?php
$file = "./hiddenaccess/test.mp3";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");             
header("Content-Length: " . filesize($file));

@readfile($file);

?>

Note: Do NOT have any other echo or print statements in this file.

海风掠过北极光 2024-10-17 09:45:40

这是我(显然是其他人?!!?)开发的一个函数就是为了做到这一点,它是一个丰富的函数,但它检查并执行所有操作。虽然调用它很简单,但却是重要的部分。我在一个类中有这个函数,但你可以将它设为一个 php 函数,因为它没有依赖其他类函数。希望这对您有帮助。

   public static function output_file($path, $filename, $mime_type='') {

    $err = 'Sorry, the file you are requesting is unavailable.';

    $filename = rawurldecode($filename);

    // check that file exists and is readable
    if (file_exists($path) && is_readable($path)) {

        /* Figure out the MIME type (if not specified) */
        $known_mime_types=array(
         "pdf" => "application/pdf",
         "txt" => "text/plain",
         "html" => "text/html",
         "htm" => "text/html",
         "exe" => "application/octet-stream",
         "zip" => "application/zip",
         "doc" => "application/msword",
         "xls" => "application/vnd.ms-excel",
         "ppt" => "application/vnd.ms-powerpoint",
         "gif" => "image/gif",
         "png" => "image/png",
         "jpeg"=> "image/jpg",
         "jpg" =>  "image/jpg",
         "php" => "text/plain"
        );

        if($mime_type==''){
            $file_extension = strtolower(substr(strrchr($filename,"."),1));
            if(array_key_exists($file_extension, $known_mime_types)){
             $mime_type=$known_mime_types[$file_extension];
            } else {
             $mime_type="application/force-download";
            };
        };

        @ob_end_clean(); //turn off output buffering to decrease cpu usage

        if(ini_get('zlib.output_compression')) { //otherwise the filesize is way off
            ini_set('zlib.output_compression', 'Off');
        }

        // get the file size and send the http headers
        $size = filesize($path);
        header("Content-Type: $mime_type");
        header('Content-Disposition: attachment; filename="'.$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');

        // multipart-download and download resuming support
        if(isset($_SERVER['HTTP_RANGE'])) {

            list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
            list($range) = explode(",", $range, 2);
            list($range, $range_end) = explode("-", $range);

            $range=intval($range);

            if(!$range_end) {
                $range_end = $size-1;
            } else {
                $range_end = intval($range_end);
            }

            $new_length = $range_end-$range+1;

            header("HTTP/1.1 206 Partial Content");
            header("Content-Length: $new_length");
            header("Content-Range: bytes $range-$range_end/$size");
        } else {
            $new_length = $size;
            header("Content-Length: " . $size);
        }

        /* output the file itself */
        $chunksize = 1*(1024*1024); //may want to change this
        $bytes_send = 0;

        if ($file = fopen($path, 'r')) {
            if(isset($_SERVER['HTTP_RANGE'])) {
                fseek($file, $range);
            }

            while(!feof($file) && (!connection_aborted()) && ($bytes_send<$new_length)) {
                $buffer = fread($file, $chunksize);
                print($buffer); //echo($buffer); // is also possible
                flush();
                $bytes_send += strlen($buffer);
            }

            fclose($file);

        } else {
            die($err);
        }

    } else {

        die($err);

    }

    die();
}

使用它会是这样的。

$path = '/var/www/site/httpdocs/upload/private/myfile.txt';
$dl_filename = 'NDA_'.time();
$mime_type = 'doc';
output_file($path,$dl_filename,$mime_type);

Here's a function I (Apparently Others?!!?) developed to do just that, it's a meaty function but it checks and does everything. To call it is simple though, the important part. I have this inside a class but you can just make it a php function as there is no other class functions it depends on. Hope this helps you.

   public static function output_file($path, $filename, $mime_type='') {

    $err = 'Sorry, the file you are requesting is unavailable.';

    $filename = rawurldecode($filename);

    // check that file exists and is readable
    if (file_exists($path) && is_readable($path)) {

        /* Figure out the MIME type (if not specified) */
        $known_mime_types=array(
         "pdf" => "application/pdf",
         "txt" => "text/plain",
         "html" => "text/html",
         "htm" => "text/html",
         "exe" => "application/octet-stream",
         "zip" => "application/zip",
         "doc" => "application/msword",
         "xls" => "application/vnd.ms-excel",
         "ppt" => "application/vnd.ms-powerpoint",
         "gif" => "image/gif",
         "png" => "image/png",
         "jpeg"=> "image/jpg",
         "jpg" =>  "image/jpg",
         "php" => "text/plain"
        );

        if($mime_type==''){
            $file_extension = strtolower(substr(strrchr($filename,"."),1));
            if(array_key_exists($file_extension, $known_mime_types)){
             $mime_type=$known_mime_types[$file_extension];
            } else {
             $mime_type="application/force-download";
            };
        };

        @ob_end_clean(); //turn off output buffering to decrease cpu usage

        if(ini_get('zlib.output_compression')) { //otherwise the filesize is way off
            ini_set('zlib.output_compression', 'Off');
        }

        // get the file size and send the http headers
        $size = filesize($path);
        header("Content-Type: $mime_type");
        header('Content-Disposition: attachment; filename="'.$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');

        // multipart-download and download resuming support
        if(isset($_SERVER['HTTP_RANGE'])) {

            list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
            list($range) = explode(",", $range, 2);
            list($range, $range_end) = explode("-", $range);

            $range=intval($range);

            if(!$range_end) {
                $range_end = $size-1;
            } else {
                $range_end = intval($range_end);
            }

            $new_length = $range_end-$range+1;

            header("HTTP/1.1 206 Partial Content");
            header("Content-Length: $new_length");
            header("Content-Range: bytes $range-$range_end/$size");
        } else {
            $new_length = $size;
            header("Content-Length: " . $size);
        }

        /* output the file itself */
        $chunksize = 1*(1024*1024); //may want to change this
        $bytes_send = 0;

        if ($file = fopen($path, 'r')) {
            if(isset($_SERVER['HTTP_RANGE'])) {
                fseek($file, $range);
            }

            while(!feof($file) && (!connection_aborted()) && ($bytes_send<$new_length)) {
                $buffer = fread($file, $chunksize);
                print($buffer); //echo($buffer); // is also possible
                flush();
                $bytes_send += strlen($buffer);
            }

            fclose($file);

        } else {
            die($err);
        }

    } else {

        die($err);

    }

    die();
}

To use it would be something like this.

$path = '/var/www/site/httpdocs/upload/private/myfile.txt';
$dl_filename = 'NDA_'.time();
$mime_type = 'doc';
output_file($path,$dl_filename,$mime_type);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文