PHP cURL - URL中发现的非法字符

时间:2017-11-09 18:54:56

标签: php curl

我正在尝试使用数据库中的URL强制下载。数据库中的URL是外部URL。

使用cURL,我正在尝试检查URL是否仍然存在:

$id = strip_tags($_GET['dl']);

// grab stuff from db
$resource = $engine->runQuery("SELECT downloadurl, section FROM resources WHERE id=:id");
$resource->execute(array(':id'=>$id));
$row = $resource->fetch(PDO::FETCH_ASSOC);

// define memberonly sections
$memberonly = array(18, 7, 16, 19, 12);

if(in_array($row['section'], $memberonly)) {
    if($engine->isLoggedin()) {
        $dlurl = $row['downloadurl'];
        $filename = basename($dlurl);

        // curl lookup
        $curl = curl_init($dlurl);
        curl_setopt($curl, CURLOPT_NOBODY, true);
        curl_exec($curl);
        $retcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);

        if($retcode == 200) { // exists
            header('Content-Type: application/octet-stream');
            header("Content-Transfer-Encoding: Binary"); 
            header("Content-disposition: attachment; filename=\"" . $filename . "\""); 
            readfile($dlurl);
            exit;
        } elseif($retcode == 404) {
            echo 'File does not exist.';
        } else {
            echo 'Server is busy. Please try again later.';
        }
    } else {
        // head to root
        header('Location: /');
    }
}

cURL一直返回0,因此我使用var_dump(curl_error($curl));来查看问题所在。它输出:

  

string(31)“在URL中找到非法字符”

这就是数据库URL的样子:

  

http://gs2.ww.prod.dl.playstation.net/gs2/ppkgo/prod/CUSA00663_00/12/f_d2245740342e84367b73efbbf753a26de0aecbd69e6a494f1bdf4626cb52d3cc/f/UP0001-CUSA00663_00-AC5GAMEPS4000001-A0105-V0100_1.pkg

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

"\u1FFE:foo".StartsWith(":")

之后添加此行$dlurl = urlencode($dlurl);

如下所示:

$filename = basename($dlurl);

还可以尝试从您的网址中删除意外的字符:

$dlurl = $row['downloadurl'];

$filename = basename($dlurl);

$dlurl = urlencode($dlurl);

最终代码如下所示:

$dlurl  = str_replace(' ', '', $dlurl ); // remove spaces
$dlurl = str_replace("\t", '', $dlurl ); // remove tabs
$dlurl = str_replace("\n", '', $dlurl ); // remove new lines
$dlurl = str_replace("\r", '', $dlurl ); // remove carriage returns

如果你这样做,则不需要$dlurl = $row['downloadurl']; $dlurl = str_replace(' ', '', $dlurl ); // remove spaces $dlurl = str_replace("\t", '', $dlurl ); // remove tabs $dlurl = str_replace("\n", '', $dlurl ); // remove new lines $dlurl = str_replace("\r", '', $dlurl ); // remove carriage returns $filename = basename($dlurl);

答案 1 :(得分:0)

即使使用缓存,文件仍然是2.1 GB,你有一个疯狂的第一次下载时间,你的PHP可能会等待很长一段时间((2.1 * 1024) / (100 / 8)) = at least 2.86 minutes at a 100 mbit/s connection + php overhead + hdd write time甚至开始文件为用户下载(因为您的服务器必须先下载它)。

由于您拥有资产的URL,因此最好只使用以下方式转发用户:

$url = 'http://gs2.ww.prod.dl.playstation.net/gs2/ppkgo/prod/CUSA00663_00/12/f_d2245740342e84367b73efbbf753a26de0aecbd69e6a494f1bdf4626cb52d3cc/f/UP0001-CUSA00663_00-AC5GAMEPS4000001-A0105-V0100_1.pkg';

header(sprintf('Location: %s', $url));
die();

优点:

  • 下载对用户来说要快得多,因为他们不必等待服务器先下载文件
  • 您可以避免占用带宽(第一位用户只需至少4.2 GB - 首先下载然后上传给用户)
  • PHP的开销更少
  • 您不会使用缓存文件填充本地服务器

缺点:

  • 您的用户可以看到文件的来源(这真的是个问题吗?)
  • 他们(playstation.net)会知道你的请求(他们可以在推荐人中看到)。如果您确实需要,可以使用https://dereferer.me/之类的服务来避免这种情况。

它基本上使得流程来自:

1. user
2.   your web server
3.     PHP
4.       playstation.net
5.     PHP
6.   your web server
7. user

1. user
2.   playstation.net
3. user