web-dev-qa-db-ja.com

PHPを使用してファイルのダウンロードを強制する

サーバーにCSVファイルがあります。ユーザーがリンクをクリックするとダウンロードされますが、代わりにブラウザウィンドウで開きます。

私のコードは次のようになります

<a href="files/csv/example/example.csv">
    Click here to download an example of the "CSV" file
</a>

これは、私がすべての開発作業を行っている通常のWebサーバーです。

私は次のようなものを試しました:

<a href="files/csv/example/csv.php">
    Click here to download an example of the "CSV" file
</a>

これで、私のcsv.phpファイル:

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=example.csv');
header('Pragma: no-cache');

現在、私の問題はダウンロード中ですが、CSVファイルではありません。新しいファイルを作成します。

62
Roland

.htaccessソリューション

サーバー上のすべてのCSVファイルを強制的にダウンロードするには、.htaccessファイルを追加します。

AddType application/octet-stream csv

PHPソリューション

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=example.csv');
header('Pragma: no-cache');
readfile("/path/to/yourfile.csv");
103
robjmills

または、HTML5を使用してこれを行うことができます。単に

<a href="example.csv" download>download not open it</a>
23
AtanuCSE

取得を要求されたURLをどう処理するかはブラウザ次第であるため、これを確実に行うことはできません。

Content-dispositionヘッダーを送信することで、すぐに「ディスクに保存」することを提供するブラウザにsuggestを指定できます。

header("Content-disposition: attachment");

これがさまざまなブラウザでどの程度サポートされているかわかりません。別の方法は、アプリケーション/オクテットストリームのコンテンツタイプを送信することですが、それはハックです(基本的には、ブラウザに「これはどんな種類のファイルかは教えません」と伝え、ブラウザはダウンロードダイアログを提供します)、Internet Explorerで問題を引き起こすと言われています。

詳細については Web Authoring FAQ。 をご覧ください。

Editデータを配信するためにPHPファイルに切り替えました-これはContent-ディスポジションヘッダー(これを行うことができるいくつかの不可解なApache設定がない限り)。あとは、そのPHPファイルがCSVファイルの内容を読み取り、それらを印刷するためだけです。ヘッダーのfilename=example.csvは、ファイルに使用する名前をクライアントブラウザーに提案するだけで、実際にはサーバー上のファイルからデータをフェッチするわけではありません。

15

より安全なブラウザソリューションを次に示します。

    $fp = @fopen($yourfile, 'rb');

    if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
    header('Content-Type: "application/octet-stream"');
    header('Content-Disposition: attachment; filename="yourname.file"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header("Content-Transfer-Encoding: binary");
    header('Pragma: public');
    header("Content-Length: ".filesize($yourfile));
}
else
{
    header('Content-Type: "application/octet-stream"');
    header('Content-Disposition: attachment; filename="yourname.file"');
    header("Content-Transfer-Encoding: binary");
    header('Expires: 0');
    header('Pragma: no-cache');
    header("Content-Length: ".filesize($yourfile));
}

fpassthru($fp);
fclose($fp);
12
Franz

メディアタイプapplication/octet-streamでファイルを送信するようにサーバーを構成します。

7
Gumbo

きれいな解決策:

<?php
    header('Content-Type: application/download');
    header('Content-Disposition: attachment; filename="example.csv"');
    header("Content-Length: " . filesize("example.csv"));

    $fp = fopen("example.csv", "r");
    fpassthru($fp);
    fclose($fp);
?>
2
vdbuilder

これは、ブラウザがこのファイルタイプを処理できることを意味します。

気に入らない場合、最も簡単な方法はZipファイルを提供することです。誰でもZipファイルを処理でき、デフォルトでダウンロード可能です。

2
StampedeXV

アプリケーション自体でそれをしている場合...このコードが役立つことを願っています。

HTML

Hrefで-URLとともにdownload_file.phpを追加する必要があります:

<a class="download" href="'/download_file.php?fileSource='+http://www.google.com/logo_small.png" target="_blank" title="YourTitle">

PHP

/* Here is the Download.php file to force download stuff */

<?php
    $fullPath = $_GET['fileSource'];
    if($fullPath) {
        $fsize = filesize($fullPath);
        $path_parts = pathinfo($fullPath);
        $ext = strtolower($path_parts["extension"]);

        switch ($ext) {
            case "pdf":
                header("Content-Disposition: attachment; filename=\"" . $path_parts["basename"]."\""); // Use 'attachment' to force a download
                header("Content-type: application/pdf"); // Add here more headers for diff. extensions
                break;

            default;
                header("Content-type: application/octet-stream");
                header("Content-Disposition: filename=\"" . $path_parts["basename"]."\"");
        }

        if($fsize) { // Checking if file size exist
            header("Content-length: $fsize");
        }
        readfile($fullPath);
        exit;
    }
?>
1
hussain

このページの以前の回答では、.htaccessを使用して特定の種類のすべてのファイルを強制的にダウンロードする方法について説明しています。ただし、このソリューションは、すべてのブラウザーのすべてのファイルタイプで機能するわけではありません。これはより信頼性の高い方法です。

<FilesMatch "\.(?i:csv)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

これが正しく機能することを確認するには、ブラウザのキャッシュをフラッシュする必要がある場合があります。

1
Chris Harrison

ダウンロードを強制するには、ほとんどのブラウザーでサポートされている_Content-Type: application/force-download_ヘッダーを使用できます。

_function downloadFile($filePath)
{
    header('Content-Type: application/force-download');
    header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
    header('Content-Length: ' . filesize($filePath));
    readfile($filePath);
}
_

より良い方法

この方法でファイルをダウンロードすることは、特に大きなファイルの場合には最適なアイデアではありません。 PHPは、ファイルの内容の読み取りと出力に余分なCPU /メモリを必要とし、大きなファイルを扱う場合、時間/メモリの制限に達する可能性があります。

より良い方法は、PHPを使用してファイルへのアクセスを認証および許可することです。実際のファイルサービスは、X-SENDFILEメソッドを使用してWebサーバーに委任する必要があります(Webサーバーの構成が必要です):

_X-SENDFILE_を処理するようにWebサーバーを設定したら、readfile($filePath)header('X-SENDFILE: ' . $filePath)に置き換えるだけで、Webサーバーがファイル処理を処理します。これにより、PHP readfile

(Nginxの場合、_X-Accel-Redirect_の代わりに_X-SENDFILE_ヘッダーを使用します)

注:最終的に空のファイルをダウンロードする場合は、_X-SENDFILE_ヘッダーを処理するようにWebサーバーを構成しなかったことを意味します。上記のリンクをチェックして、Webサーバーを正しく構成する方法を確認してください。

0
Dima L.