我目前正在创建一项允许从远程服务器下载文件的功能。我的脚本适用于所需的所有文件类型,但由于某种原因它不适用于msg文件(它下载空文件(0K))。顺便说一下Chrome和IE中的行为相同。我认为问题在于文件大小,所以我已经测试过下载大型zip文件,它也运行正常,似乎只有msg文件我遇到了问题。
我的剧本:
// 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");
readfile($file_url);
exit;
我做错了什么?
P.S。我认为可行的解决方案是在上传过程中存档(zip).msg文件,然后将其下载为.zip,但我正在寻找更好的解决方案。
答案 0 :(得分:3)
您尝试将readfile
与URL文件位置一起使用,只有在fopen wrappers启用后才可以使用。
来自PHP readfile:
提示如果fopen wrappers,则可以使用此功能将URL用作文件名 已启用。有关如何操作的详细信息,请参阅fopen() 指定文件名。请参阅Supported Protocols and Wrappers 链接到有关各种包装器具有哪些功能的信息, 关于它们的使用和它们的任何预定义变量的信息的注释 可能会提供。
这不安全,你应该使用像这样的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 :(得分: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 :(得分:2)
尝试使用其他内容类型:
header("Content-Type: application/download");
答案 3 :(得分:1)
可能是一个愚蠢的问题,但是,你试过一个简单的
$fileurl="http://example.com/file.msg";
$fileContent = file_get_contents($fileurl);
file_put_contents($saveDir.$fileName, $fileContent);
答案 4 :(得分:1)
尝试添加用户代理并接受请求中的所有MIME类型..使用cURL:
// 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;
答案 5 :(得分: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;
答案 6 :(得分:0)
我认为您必须指定Content-lenght标头,我认为禁用缓存也可能有所帮助。
例如:
header("Content-length: " . strlen($output); // tells file size
header("Pragma: no-cache");
header("Expires: 0");