developer tip

PHP를 사용하여 강제로 파일 다운로드

copycodes 2020. 11. 26. 18:46
반응형

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파일 의 내용 :

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

이제 내 문제는 다운로드 중이지만 CSV 파일은 아닙니다. 새 파일을 생성합니다.


.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 에서 이에 대한 자세한 내용을 읽어보십시오 .

편집 이미 데이터를 전달하기 위해 PHP 파일로 전환했습니다. 이는 Content-disposition 헤더를 설정하는 데 필요합니다 (이를 수행 할 수있는 일부 아파치 설정이없는 경우). 이제 남은 일은 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);
?>

A previous answer on this page describes how to use .htaccess to force all files of a certain type to download. However, the solution does not work with all file types across all browsers. This is a more reliable way:

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

You might need to flush your browser cache to see this working correctly.


If you are doing it with your application itself... I hope this code helps.

HTML

In href -- you have to add download_file.php along with your 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;
    }
?>

To force download you may use Content-Type: application/force-download header, which is supported by most browsers:

function downloadFile($filePath)
{
    header("Content-type: application/octet-stream");
    header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
    header('Content-Length: ' . filesize($filePath));
    readfile($filePath);
}

A BETTER WAY

Downloading files this way is not the best idea especially for large files. PHP will require extra CPU / Memory to read and output file contents and when dealing with large files may reach time / memory limits.

A better way would be to use PHP to authenticate and grant access to a file, and actual file serving should be delegated to a web server using X-SENDFILE method (requires some web server configuration):

After configuring web server to handle X-SENDFILE, just replace readfile($filePath) with header('X-SENDFILE: ' . $filePath) and web server will take care of file serving, which will require less resources than using PHP readfile.

(For Nginx use X-Accel-Redirect header instead of X-SENDFILE)

Note: If you end up downloading empty files, it means you didn't configure your web server to handle X-SENDFILE header. Check the links above to see how to correctly configure your web server.

참고URL : https://stackoverflow.com/questions/1465573/forcing-to-download-a-file-using-php

반응형