PHP解决Safari浏览器下载文件文件名称乱码的问题

2023-12-20 07:34:48

【项目背景】

项目中开发了统一的文件管理器,在其余如IE,Chrome,Firefox等下载正常,可是在苹果Safari浏览器下载就会出现中文名称乱码问题。

【理论知识】

主要是下载Header头不符合RFC规范致使。参考文章:http://www.sohu.com/a/334506221_463987

【如何解决】

设置统一的下载Header头以下:

<?php
/**
 * 获取下载文件所需headers头信息
 *
 * @param string $filename
 * @param string $charset 默认UTF-8
 * @param string $mimeType 默认application/octet-stream
 * @return array
 */
function downloadHeaders($filename, $charset = 'UTF-8', $mimeType = 'application/octet-stream')
{
	// 兼容各浏览器下载文件名乱码问题
	if (preg_match("/MSIE/", $_SERVER["HTTP_USER_AGENT"])) {
		$filename = urlencode($filename);
		// 替换空格
		$filename = str_replace("+", "%20", $filename);
		$attachment = "attachment; filename=\"{$filename}\"; charset={$charset}";
	} else if (preg_match("/Firefox/", $_SERVER["HTTP_USER_AGENT"])) {
		$attachment = 'attachment; filename*=utf-8\'\'' . $filename;
	} else if (preg_match("/(Safari|MicroMessenger)/", $_SERVER["HTTP_USER_AGENT"])) {
		$filename = rawurlencode($filename);
		// 注意:rawurlencode与urlencode的区别
		$attachment = 'attachment; filename*=utf-8\'\'' . $filename;
	} else {
		$attachment = "attachment; filename=\"{$filename}\"; charset={$charset}";
	}

	$headers = [
		'Cache-Control' => 'public, must-revalidate, max-age=0',
		'Content-Type' => $mimeType,
		'Content-Disposition' => $attachment,
	];
	return $headers;
}

/**
 * 判断文件是否存在,包含远程文件
 *
 * @param string $file
 * @return bool
 */
function m_file_exists($file)
{
	if (preg_match('/^http(s)?:\/\//', $file)) {
		//远程文件
		if (ini_get('allow_url_fopen')) {
			if (@fopen($file, 'r')) {
				return true;
			}
		} else {
			$parseurl = parse_url($file);
			$host = $parseurl['host'];
			$path = $parseurl['path'];
			$fp = fsockopen($host, 80, $errno, $errstr, 5);
			if (!$fp) {
				return false;
			}
			fputs($fp, "GET {$path} HTTP/1.1 \r\nhost:{$host}\r\n\r\n");
			if (preg_match('/HTTP\/1.1 200/', fgets($fp, 1024))) {
				return true;
			}
		}
		return false;
	}
	return file_exists($file);
}

header('Content-Type: text/html; charset=utf-8');

if ($_GET["type"] == 2) {
	// https://abc.cde.com/filedownload.php?type=2&fileurl=https%3A%2F%2Fabc.cde.com%2Fpwpublic%2F%E4%BA%BA%E5%91%98%E5%90%8D%E5%8D%95%E6%A8%A1%E6%9D%BF.xlsx&filename=%E4%BA%BA%E5%91%98%E5%90%8D%E5%8D%95%E6%A8%A1%E6%9D%BFtest.xlsx

	// http://localhost/filedownload.php?type=2&fileurl=https%3A%2F%2Fabc.cde.com%2Fpwpublic%2F%E4%BA%BA%E5%91%98%E5%90%8D%E5%8D%95%E6%A8%A1%E6%9D%BF.xlsx&filename=%E4%BA%BA%E5%91%98%E5%90%8D%E5%8D%95%E6%A8%A1%E6%9D%BFtest.xlsx

	// https://abc.cde.com/filedownload.php?type=2&fileurl=urlencode{文件下载地址}&filename=urlencode{文件名}
	// $file_name ='人员名单模板.xlsx';
	// $file_path = 'https://abc.cde.com/pwpublic/人员名单模板.xlsx';
	$file_name = urldecode($_GET["filename"]);
	$file_path = urldecode($_GET["fileurl"]);
} else {
	$file_name = '团体人员名单模板.xlsx';
	$file_path = '/home/www/xxx/public/团体人员名单模板.xlsx';
}
if (m_file_exists($file_path) == false) {
	echo '文件不存在';
	exit;
}

$headers = downloadHeaders($file_name);
foreach ($headers as $k => $v) {
	header($k . ':' . $v);
}
readfile($file_path);
?>

文章来源:https://blog.csdn.net/lvshuocool/article/details/135082253
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。