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



我正试图使用数据库中的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

如何解决此问题?

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

如下所示:

$dlurl = $row['downloadurl'];
$filename = basename($dlurl);
$dlurl = urlencode($dlurl);

也可以尝试从你的url中删除意外的charecter:

$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);

如果你这样做,就不需要urlencode.

考虑到文件是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

最新更新