欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

分享一个超好用的php header下载函数

程序员文章站 2023-11-26 14:37:04
复制代码 代码如下:

复制代码 代码如下:

<?php
/**
 * 发送文件
 *
 * @author: legend(legendsky@hotmail.com)
 * @link: http://www.ugia.cn/?p=109
 * @description: send file to client
 * @version: 1.0
 *
 * @param string   $filename      文件名称或路径
 * @param string   $fancyname     自定义的文件名,为空则使用filename
 * @param boolean  $forcedownload 是否强制下载
 * @param integer  $speedlimit    速度限制,单位为字节,0为不限制,不支持windows服务器
 * @param string   $$contenttype  文件类型,默认为application/octet-stream
 *
 * @return boolean
 */
function sendfile($filename, $fancyname = '', $forcedownload = true, $speedlimit = 0, $contenttype = '')
{
    if (!is_readable($filename))
    {
        header("http/1.1 404 not found");
        return false;
    }

    $filestat = stat($filename);
    $lastmodified = $filestat['mtime'];

    $md5 = md5($filestat['mtime'] .'='. $filestat['ino'] .'='. $filestat['size']);
    $etag = '"' . $md5 . '-' . crc32($md5) . '"';

    header('last-modified: ' . gmdate("d, d m y h:i:s", $lastmodified) . ' gmt');
    header("etag: $etag");

    if (isset($_server['http_if_modified_since']) && strtotime($_server['http_if_modified_since']) >= $lastmodified)
    {
        header("http/1.1 304 not modified");
        return true;
    }

    if (isset($_server['http_if_unmodified_since']) && strtotime($_server['http_if_unmodified_since']) < $lastmodified)
    {
        header("http/1.1 304 not modified");
        return true;
    }

    if (isset($_server['http_if_none_match']) &&  $_server['http_if_none_match'] == $etag)
    {
        header("http/1.1 304 not modified");
        return true;
    }

    if ($fancyname == '')
    {
        $fancyname = basename($filename);
    }

    if ($contenttype == '')
    {
        $contenttype = 'application/octet-stream';
    }

    $filesize = $filestat['size'];  

    $contentlength = $filesize;
    $ispartial = false;

    if (isset($_server['http_range']))
    {
        if (preg_match('/^bytes=(d*)-(d*)$/', $_server['http_range'], $matches))
        {   
            $startpos = $matches[1];
            $endpos = $matches[2];

            if ($startpos == '' && $endpos == '')
            {
                return false;
            }

            if ($startpos == '')
            {
                $startpos = $filesize - $endpos;
                $endpos = $filesize - 1;
            }
            else if ($endpos == '')
            {
                $endpos = $filesize - 1;
            }

            $startpos = $startpos < 0 ? 0 : $startpos;
            $endpos = $endpos > $filesize - 1 ? $filesize - 1 : $endpos;

            $length = $endpos - $startpos + 1;

            if ($length < 0)
            {
                return false;
            }

            $contentlength = $length;
            $ispartial = true;
        }
    }

    // send headers
    if ($ispartial)
    {
        header('http/1.1 206 partial content');
        header("content-range: bytes $startpos-$endpos/$filesize");

    }
    else
    {
        header("http/1.1 200 ok");
        $startpos = 0;
        $endpos = $contentlength - 1;
    }

    header('pragma: cache');
    header('cache-control: public, must-revalidate, max-age=0');
    header('accept-ranges: bytes');
    header('content-type: ' . $contenttype);
    header('content-length: ' . $contentlength);

    if ($forcedownload)
    {
        header('content-disposition: attachment; filename="' . rawurlencode($fancyname). '"');//汉字自动转为url编码
  header('content-disposition: attachment; filename="' . $fancyname. '"');
    }

    header("content-transfer-encoding: binary");

    $buffersize = 2048;

    if ($speedlimit != 0)
    {
        $packettime = floor($buffersize * 1000000 / $speedlimit);
    }

    $bytessent = 0;
    $fp = fopen($filename, "rb");
    fseek($fp, $startpos);

    //fpassthru($fp);

    while ($bytessent < $contentlength && !feof($fp) && connection_status() == 0 )
    {
        if ($speedlimit != 0)
        {
            list($usec, $sec) = explode(" ", microtime());
            $outputtimestart = ((float)$usec + (float)$sec);
        }

        $readbuffersize = $contentlength - $bytessent < $buffersize ? $contentlength - $bytessent : $buffersize;
        $buffer = fread($fp, $readbuffersize);       

        echo $buffer;

        ob_flush();
        flush();

        $bytessent += $readbuffersize;

        if ($speedlimit != 0)
        {
            list($usec, $sec) = explode(" ", microtime());
            $outputtimeend = ((float)$usec + (float)$sec);

            $usetime = ((float) $outputtimeend - (float) $outputtimestart) * 1000000;
            $sleeptime = round($packettime - $usetime);
            if ($sleeptime > 0)
            {
                usleep($sleeptime);
            }
        }
    }
   

    return true;
}
 ?>