2

我真的很坚持。我做了一个如下的功能(一个wp插件)。处理下载请求。

下载url格式是这样的:

http://mysite.com/?download=2f547re8w9qasd547g8tr52e15469879w

文件将像往常一样保存在浏览器中(弹出“另存为...”框)。

问题是:

1 -下载管理器喜欢Orbit尝试下载页面!并且IDM只下载整个文件大小的一小部分(例如7%)然后停止并通过恢复,它从第一个开始下载。(浏览器完全下载文件并恢复没有问题)

2 -当(通过浏览器)下载 .zip 文件时,出现“存档意外结束”错误。(zip 文件详细信息中的 CRC32 显示 0 个字符

function save_file()
{
    global $wpdb;
    global $uid;
    global $each_download;
    $hash = @$_GET["download"];
    if(preg_match('/^[a-z0-9]{32}$/i',$hash))
    {
        if($row = $wpdb->get_row("SELECT * FROM wp_dlurl WHERE hash = '{$hash}'",ARRAY_A))
        {
            if(is_user_logged_in())
            {
                if($row['price'] != 0)
                    $each_download = $row['price'];
                if(get_user_meta($uid, 'revo_credits', true) >= $each_download)
                {
                    $parts = pathinfo($row['url']);
                    $url = $parts['dirname'] . '/' . urlencode($parts['basename']);
                    $file = pathinfo($row['filename']);
                    $ext = $file['extension'];
                    /* List of File Types */ 
                    $fileTypes['swf'] = 'application/x-shockwave-flash'; 
                    $fileTypes['pdf'] = 'application/pdf'; 
                    $fileTypes['exe'] = 'application/octet-stream'; 
                    $fileTypes['zip'] = 'application/zip'; 
                    $fileTypes['doc'] = 'application/msword'; 
                    $fileTypes['xls'] = 'application/vnd.ms-excel'; 
                    $fileTypes['ppt'] = 'application/vnd.ms-powerpoint'; 
                    $fileTypes['gif'] = 'image/gif'; 
                    $fileTypes['png'] = 'image/png'; 
                    $fileTypes['jpeg'] = 'image/jpg'; 
                    $fileTypes['jpg'] = 'image/jpg'; 
                    $fileTypes['rar'] = 'application/rar';     

                    $fileTypes['ra'] = 'audio/x-pn-realaudio'; 
                    $fileTypes['ram'] = 'audio/x-pn-realaudio'; 
                    $fileTypes['ogg'] = 'audio/x-pn-realaudio'; 

                    $fileTypes['wav'] = 'video/x-msvideo'; 
                    $fileTypes['wmv'] = 'video/x-msvideo'; 
                    $fileTypes['avi'] = 'video/x-msvideo'; 
                    $fileTypes['asf'] = 'video/x-msvideo'; 
                    $fileTypes['divx'] = 'video/x-msvideo'; 

                    $fileTypes['mp3'] = 'audio/mpeg'; 
                    $fileTypes['mp4'] = 'audio/mpeg'; 
                    $fileTypes['mpeg'] = 'video/mpeg'; 
                    $fileTypes['mpg'] = 'video/mpeg'; 
                    $fileTypes['mpe'] = 'video/mpeg'; 
                    $fileTypes['mov'] = 'video/quicktime'; 
                    $fileTypes['swf'] = 'video/quicktime'; 
                    $fileTypes['3gp'] = 'video/quicktime'; 
                    $fileTypes['m4a'] = 'video/quicktime'; 
                    $fileTypes['aac'] = 'video/quicktime'; 
                    $fileTypes['m3u'] = 'video/quicktime';

                    $contentType = $fileTypes[$ext];
                    //ob_end_clean();
                    header("Cache-Control: public");
                    header('Content-Type: $contentType');
                    header("Content-Transfer-Encoding: binary");
                    $new_name = $row['filename'];//rand(1000,999999).".".$ext;
                    $contentDisposition = 'attachment';
                    if(strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
                    {
                        $new_name = preg_replace('/\./', '%2e', $new_name, substr_count($new_name,'.') - 1);
                    }
                    $new_name = urlencode($new_name);
                    header("Content-Disposition: $contentDisposition; filename=\"$new_name\"");
                    header("Accept-Ranges: bytes");
                    $range = 0; 
                    $size = $row['size']; 
                    if(isset($_SERVER['HTTP_RANGE']))
                    {
                        list($a, $range) = explode("=",$_SERVER['HTTP_RANGE']); 
                        str_replace($range, "-", $range); 
                        $size2 = $size-1; 
                        $new_length = $size-$range; 
                        header("HTTP/1.1 206 Partial Content"); 
                        header("Content-Length: $new_length"); 
                        header("Content-Range: bytes $range$size2/$size"); 
                    }
                    else
                    {
                        update_user_meta($uid, 'revo_credits', get_user_meta($uid, 'revo_credits', true)-$each_download);
                        $size2 = $size-1; 
                        header("Content-Range: bytes 0-$size2/$size"); 
                        header("Content-Length: ".$size);
                    }
                    if ($size == 0)
                    {
                        showMessage('aborted. zero file size');
                    } 
                    set_magic_quotes_runtime(0);
                    $maxSpeed = 200;            
                    $fp = fopen($url,"rb");
                    fseek($fp,$range);
                    while(!feof($fp) and (connection_status()==0)) 
                    { 
                        set_time_limit(0); 
                        print(fread($fp,1024*$maxSpeed)); 
                        flush(); 
                        ob_flush(); 
                        sleep(1); 
                    } 
                    fclose($fp); 
                    return((connection_status()==0) and !connection_aborted());
                }
                else
                    showMessage("not enough credit.");
            }
            else
                showMessage("login to download.");
        }
        else
        {
            wp_redirect(get_bloginfo('url'));
            exit;
        }
    }
    else
    {
        wp_redirect(get_bloginfo('url'));
        exit;
    }
}

我认为标题是罪魁祸首!


Accept-ranges使用和标题的恢复方法Content-length已经完成,并且在通过浏览器下载文件时有效。

4

1 回答 1

1

不确定其他下载如何工作,但您的范围实现错误,为什么?

你变得range像这样

$_SERVER['HTTP_RANGE'] = "bytes=1-200"; //sample range
$size = 1000; //sample size

list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']);
str_replace($range, "-", $range);
$size2 = $size - 1;
$new_length = $size - $range;

// Used Print Insted of headers
print("HTTP/1.1 206 Partial Content\n");
print("Content-Length: $new_length\n");
print("Content-Range: bytes $range$size2/$size\n");

输出

HTTP/1.1 206 Partial Content
Content-Length: 999
Content-Range: bytes 1-200999/1000   <------ This is an issue 

我期待这样的事情

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

// Used Print Insted of headers
print("HTTP/1.1 206 Partial Content\n");
print("Content-Length: $length\n");
printf('Content-Range: bytes %d-%d/%d', $offset, ($offset + $length), $size)

输出

HTTP/1.1 206 Partial Content
Content-Length: 199
Content-Range: bytes 1-200/1000   <---- Properly Displayed
于 2013-04-07T20:42:13.273 回答