2017-03-01 118 views
3

我目前正在创建一个功能,允许从远程服务器下载文件。我的脚本适用于所有需要的文件类型,但由于某种原因它不适用于msg文件(它下载空文件(0K))。顺便说一句,在Chrome和IE中同样的行为。我认为问题是与文件大小,所以我已经测试下载大型压缩文件,它也工作正常,似乎只有味精文件我有问题。如何使用PHP下载msg文件

我的脚本:

我做错了吗?

P.S.我认为可能的解决方案是在上传过程中存档(zip).msg文件,然后将其下载为.zip,但我正在寻找更好的解决方案。

+0

不是一个答案,但对于你的脚本一个建议:你应该清理你的'$ _GET [ 'FILE_NAME']',以避免有人通过这样的东西'../ passwd' –

+2

您可以从远程服务器下载PHP脚本运行所在的服务器的.msg文件,例如:用'wget http:// mypath/uploads/test.msg'?我用本地文件测试了你的脚本,例如。 '$ file_url ='test.msg';',这是在这里工作,所以我怀疑是从远程服务器获取它的问题。您也可以检查'readfile'的返回值 - 如果它是'false',则读取文件时会出错。 –

+0

我测试了脚本,它下载了远程'msg'文件。 nginx + php 5.6。你确定脚本有权下载文件吗?如果它是'mypath'中的服务器,那不会提供'.msg'文件呢? –

回答

3

扩展my comment到一个答案:

我有一个本地文件,例如测试脚本。 $file_url = 'test.msg';,这是在这里工作。所以我怀疑是从远程服务器获取文件时出现问题。你能否通过PHP以外的其他方式从运行PHP脚本的服务器下载远程.msg文件,例如。与wget http://mypath/uploads/test.msg?您还可以检查readfile的返回值 - if it is false, there is an error reading the file。如果您无法下载该文件或者readfile返回false,那么问题不在您的代码中,而是您必须首先解决的服务器配置或连接问题。

关于你的代码:你应该清理你的$_GET['file_name'],以避免有人通过像../passwd这样的东西。

2

尝试使用其他内容类型:

header("Content-Type: application/download"); 
+0

我刚刚尝试使用另一个标题,但仍然没有喜悦,同样的问题! –

+0

@DenissMuntjans更新了尝试这一个:) – EL3PHANTEN

+0

仍然一样,它下载空msg文件! –

3

您正在尝试使用readfile一个URL文件的位置,这是可能的,只有fopen wrappers已启用。

从PHP readfile

提示的URL可如果fopen wrappers 已启用作为具有这种功能的文件名。有关如何 指定文件名的更多详细信息,请参阅fopen()。有关 可能提供的有关各种包装具有哪些功能的信息的链接,请参阅Supported Protocols and Wrappers的链接, 关于其使用的注释以及有关任何预定义变量的信息。

这不是安全的,你应该使用本地系统路径insted的这样一个URL:

// Get parameter form html page 
if(isset($_GET['file_name'])) $file_name = $_GET['file_name']; 

$file_name = str_replace('"', '\\"', $file_name); 
//$file_url = 'http://mypath/uploads/' . $file_name; 
// The script is located to one level up directory of the uploads directory 
// You can change this to fit your script and uploads directory locations 
$uploads_local_path = __DIR__.'/uploads/'; 
$file_path = $uploads_local_path.$file_name; 

header('Content-Type: application/octet-stream'); 
header("Content-disposition: attachment; filename=\"".$file_name."\""); 
header("Content-Transfer-Encoding: Binary"); 

readfile($file_path); 
exit; 

,现在它的工作原理,并下载该文件。请注意并且有uploads目录的正确路径位置。

你甚至可以尝试我的地方例如基于您的代码在这里和下载文件:http://zikro.gr/dbg/php/dl-file/

直接链接到下载脚本,你可以尝试:http://zikro.gr/dbg/php/dl-file/dodl.php?file_name=1011191_orig.png

1

尝试添加用户代理并接受您的请求中的所有MIME类型。通过使用卷曲:

// Get parameter form html page 
if(isset($_GET['file_name'])) $file_name = $_GET['file_name']; 

$file_name = str_replace('"', '\\"', $file_name); 
$file_url = 'http://mypath/uploads/' . $file_name; 

header('Content-Type: application/octet-stream'); 
header("Content-disposition: attachment; filename=\"".$file_name."\""); 
header("Content-Transfer-Encoding: Binary"); 

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $file_url); 
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0'); 
$headerData[] = 'Accept: */*'; 
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerData); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
$data = curl_exec ($ch); 
$error = curl_error($ch); 
curl_close($ch); 
echo $data; 
exit; 
1

试试吧

// Get parameter form html page 
if(isset($_GET['file_name'])) $file_name = $_GET['file_name']; 

$file_name = str_replace('"', '\\"', $file_name); 
$file_url = 'http://mypath/uploads/' . $file_name; 

header("Content-Type: application/download"); 
header("Content-disposition: attachment; filename=\"".$file_name."\""); 
header("Content-Transfer-Encoding: Binary"); 

readfile($file_url); 
exit; 
0

我认为你必须指定Content-lenght标题,我认为禁用缓存也可能有帮助。

例如:

header("Content-length: " . strlen($output); // tells file size 
header("Pragma: no-cache"); 
header("Expires: 0");