ホームページ >バックエンド開発 >PHPチュートリアル >PHP でファイルを効率的かつ迅速にダウンロードする方法

PHP でファイルを効率的かつ迅速にダウンロードする方法

WBOY
WBOYオリジナル
2016-06-20 13:01:301165ブラウズ

一般的に言えば、ドキュメント ルートの下にあるファイルへの URL を直接指定することで、ユーザーにファイルをダウンロードさせることができます。

ただし、これを行うと、統計や権限チェックなどを行うことができなくなります。そのため、多くの場合、PHP を使用して転送を行い、ユーザーにファイルのダウンロードを提供します。

<?php

$file="/tmp/dummy.tar.gz";

header("Content-type: application/octet-stream");

header('Content-Disposition: attachment; filename="'.basename($file).'"');

header("Content-Length: ".filesize($file));

readfile($file);

しかし、これには問題があります。ファイル名が中国語の場合、一部のユーザーは文字化けしたファイル名をダウンロードする可能性があります。

それでは、いくつかの変更を加えてみましょう (参照:

<?php
$file="/tmp/中文名.tar.gz";
$filename=basename($file);
header("Content-type: application/octet-stream");
//处理中文文件名

$ua=$_SERVER["HTTP_USER_AGENT"];

$encoded_filename=urlencode($filename);

$encoded_filename=str_replace("+","%20",$encoded_filename);

if(preg_match("/MSIE/",$ua)){

header('Content-Disposition: attachment; filename="'.$encoded_filename.'"');

}elseif(preg_match("/Firefox/",$ua)){

header("Content-Disposition: attachment; filename*=\"utf8''".$filename.'"');

}else{

header('Content-Disposition: attachment; filename="'.$filename.'"');

}

header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Length: ".filesize($file));
readfile($file);

これでかなり良くなったように見えますが、まだ問題があり、それは PHP の readfile です。PHP の readfile は可能な限り効率的であり、PHP 自体のメモリを占有しないように努めていますが、実際には依然として MMAP を使用する必要があります (サポートされている場合)、またはループでファイルを読み取り、直接出力するための固定バッファー。

出力する場合、Apache + PHP mod の場合は、Apache の出力バッファに送信する必要があります。Nginx + fpm の場合は、別々にデプロイされている場合も同様です。追加のネットワーク IO。

では、Web サーバーは PHP 層を経由せずにユーザーにファイルを直接送信できるのでしょうか?

今日、興味深い記事を見つけました: How I PHP: X-SendFile.

Apache のモジュール mod_xsendfile を使用すると、Apache がこのファイルをユーザーに直接送信できるようになります。

<?php
$file="/tmp/中文名.tar.gz";
$filename=basename($file);
header("Content-type: application/octet-stream");
//处理中文文件名
$ua=$_SERVER["HTTP_USER_AGENT"];
$encoded_filename=urlencode($filename);
$encoded_filename=str_replace("+","%20",$encoded_filename);
if(preg_match("/MSIE/",$ua)){
header('Content-Disposition: attachment; filename="'.$encoded_filename.'"');
}elseif(preg_match("/Firefox/",$ua)){
header("Content-Disposition: attachment; filename*=\"utf8''".$filename.'"');
}else{
header('Content-Disposition: attachment; filename="'.$filename.'"');
}
header('Content-Disposition: attachment; filename="'.basename($file).'"');

//Xsendfile にファイルを送信させます

header("X-Sendfile: $file");

X-Sendfile ヘッダーは Apache によって処理され、応答ファイルはクライアントに直接送信されます。

Lighttpd と Nginx にも同様のモジュールがあります。興味がある場合は、チェックしてください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。