我开发了一个很好的“强制下载文件”脚本,其目的是确保提供下载文件而不是在浏览器中显示,无论文件类型是什么。
它曾经运作良好,但最近我收到反馈,它不起作用,特别是对于pdf和xls文件(MS Excel)。在PDF的情况下,该文件被检测为“无效”,或者在xls文件的情况下,该文件在其内容之上获取部分html文件目录页。
我的功能究竟出了什么问题?
在这里。请注意,它可以使用URL或本地路径。
function offerToDownloadFile($filename, $access_type='url') {
/*
PHP FORCE DOWNLOAD SCRIPT
*/
// required for IE, otherwise Content-disposition is ignored
if (ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');
if($access_type === 'url') {
// access type is via the file 's url
$parsed_url = parse_url($filename);
$fileinfo = pathinfo($filename);
$parsed_url['extension'] = $fileinfo['extension'];
$parsed_url['filename'] = $fileinfo['basename'];
$parsed_url['localpath'] = LOCALROOT . $parsed_url['path'];
}
else {
// access type is the local file path
$fileinfo = pathinfo($filename);
$parsed_url['localpath'] = $filename;
$parsed_url['filename'] = basename($filename);
$parsed_url['extension'] = $fileinfo['extension'];
}
// just in case there is a double slash created when joining document_root and path
$parsed_url['localpath'] = preg_replace('/\/\//', '/', $parsed_url['localpath']);
if (!file_exists($parsed_url['localpath'])) {
die('File not found: ' . $parsed_url['localpath']);
}
$allowed_ext = array('ics','pdf', 'png', 'jpg', 'jpeg', 'zip', 'doc', 'xls', 'gif', 'exe', 'ppt','ai','psd','odt');
if (!in_array($parsed_url['extension'], $allowed_ext)) {
die('This file type is forbidden.');
}
switch ($parsed_url['extension']) {
case "ics": $ctype="text/calendar";
break;
case "pdf": $ctype = "application/pdf";
break;
case "exe": $ctype = "application/octet-stream";
break;
case "zip": $ctype = "application/zip";
break;
case "doc": $ctype = "application/msword";
break;
case "xls":
$ctype = "application/vnd.ms-excel";
break;
case "ppt": $ctype = "application/vnd.ms-powerpoint";
break;
case "gif": $ctype = "image/gif";
break;
case "png": $ctype = "image/png";
break;
case "jpeg":
case "jpg": $ctype = "image/jpg";
break;
default: $ctype = "application/force-download";
}
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false); // required for certain browsers
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"" . $parsed_url['filename'] . "\";");
header("Content-Transfer-Encoding: binary");
// header("Content-Length: " . filesize($parsed_url['localpath']));
readfile($parsed_url['localpath']);
clearstatcache();
die();
exit();
}
答案 0 :(得分:1)
强制下载文件而不是查看文件几乎无法实现,无论你如何处理它 - 像Adobe的PDF Viewer这样的第三方组件只能强迫事物忽略Content-Disposition标题并做它喜欢的事情。如果您与公众打交道,您必须接受用户将获取数据,而他们或他们的软件不会决定他们如何使用这些数据。
答案 1 :(得分:1)
该脚本现在可以使用了。我不得不改为使用此header()调用。我真的不知道为什么,这是试验和错误导致我找到这个解决方案。
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"" . $parsed_url['filename'] . "\";");
header("Content-Transfer-Encoding: binary");
header('Accept-Ranges: bytes');
header("Cache-control: private");
header('Pragma: private');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
答案 2 :(得分:0)
我不确定这是否会有所帮助,但也尝试放下以下标题:
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
MS和PDF(以及许多其他人)的问题是它们被迫用3PP软件打开,例如MS Excel,并且忽略了内容处置。
如果以上操作不起作用,用户必须右键单击并选择另存为;可能不是解决问题的最佳方案。
答案 3 :(得分:0)
可能值得考虑强制下载的.htaccess替代方案,例如:
AddType application/octet-stream csv
AddType application/octet-stream pdf
AddType application/octet-stream xls