Принуждение к загрузке файла с помощью PHP


у меня есть CSV-файл на моем сервере. Если пользователь нажимает на ссылку, он должен загрузить, но вместо этого он открывается в окне моего браузера.

мой код выглядит следующим образом

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

это обычный сервер, где у меня все мои разработки.

я попробовал что-то вроде:

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

теперь содержимое моего csv.php file:

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

теперь моя проблема в том, что это загрузка, но не мой CSV-файл. Он создает новый файл.

10 60

10 ответов:

.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");

или вы можете сделать это с помощью HTML5. Просто с

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

это не может быть сделано надежно, так как это до браузера, чтобы решить, что делать с URL-адресом, который было предложено получить.

Вы можете предлагаю в браузер, который он должен предложить" сохранить на диск " сразу же, отправив заголовок Content-disposition:

header("Content-disposition: attachment");

Я не уверен, насколько хорошо это поддерживается различными браузерами. Альтернативой является отправка типа контента приложения / октет-потока, но это хак (вы в основном рассказываете браузер "я не говорю вам, что это за файл" и в зависимости от того, что большинство браузеров будут предлагать диалог загрузки) и якобы вызывает проблемы с Internet Explorer.

подробнее об этом читайте в веб-создание FAQ.

Edit вы уже переключились на PHP - файл для доставки данных, что необходимо для установки заголовка Content-disposition (если только нет некоторых тайных настроек Apache, которые также могут это сделать). Теперь все, что осталось сделать, это для этого PHP - файла, чтобы прочитать содержимое файла CSV и распечатать их -filename=example.csv в заголовке только подсказывает браузеру клиента, какое имя использовать для файла, он фактически не извлекает данные из файла на сервере.

вот более безопасное для браузера решение:

    $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);

настройка сервера для отправки файла с типом носителя application/octet-stream.

Это означает, что ваш браузер может обрабатывать файлы этого типа.

Если вам это не нравится, самый простой способ будет предлагать ZIP-файлы. Каждый может обрабатывать ZIP-файлы, и они загружаются по умолчанию.

хорошее чистое решение:

<?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);
?>

предыдущий ответ на этой странице описывается, как использовать .htaccess для принудительной загрузки всех файлов определенного типа. Однако решение не работает со всеми типами файлов во всех браузерах. Это более надежный способ:

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

вам может потребоваться очистить кэш браузера, чтобы увидеть, что это работает правильно.

Если вы делаете это с самого приложения... Надеюсь этот код поможет.

HTML

в href-вы должны добавить download_file.php вместе с вашим URL:

<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;
    }
?>

для начала загрузки вы можете использовать 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 потребует дополнительного процессора / памяти для чтения и вывода содержимого файла, а при работе с большими файлами может достигать ограничений по времени / памяти.

лучшим способом было бы использовать PHP для аутентификации и предоставления доступа к файлу и фактическому файлу обслуживание должно быть делегировано веб-серверу с помощью метода X-SENDFILE (требуется некоторая конфигурация веб-сервера):

после настройки веб-сервера для обработки X-SENDFILE, просто заменить readfile($filePath) С header('X-SENDFILE: ' . $filePath) и веб-сервер будет заботиться о обслуживании файлов, что потребует меньше ресурсов, чем использование PHP readfile.

(для Nginx используйте X-Accel-Redirect заголовок вместо X-SENDFILE)

Примечание: Если вы в конечном итоге скачивание пустые файлы, это означает, что вы не настроили свой веб-сервер для обработки X-SENDFILE заголовок. Проверьте ссылки выше, чтобы увидеть, как правильно настроить веб-сервер.