Forcing to download a file using PHP

前端 未结 10 941
借酒劲吻你
借酒劲吻你 2020-11-22 04:04

I have a CSV file on my server. If a user clicks on a link it should download, but instead it opens up in my browser window.

My code looks as follows



        
相关标签:
10条回答
  • 2020-11-22 04:21

    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.

    0 讨论(0)
  • 2020-11-22 04:22

    Here is a more browser-safe solution:

        $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);
    
    0 讨论(0)
  • 2020-11-22 04:24

    .htaccess Solution

    To brute force all CSV files on your server to download, add in your .htaccess file:

    AddType application/octet-stream csv
    

    PHP Solution

    header('Content-Type: application/csv');
    header('Content-Disposition: attachment; filename=example.csv');
    header('Pragma: no-cache');
    readfile("/path/to/yourfile.csv");
    
    0 讨论(0)
  • 2020-11-22 04:24

    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;
        }
    ?>
    
    0 讨论(0)
  • 2020-11-22 04:30

    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):

    • X-SENDFILE is natively supported by Lighttpd: https://redmine.lighttpd.net/projects/1/wiki/X-LIGHTTPD-send-file
    • Apache requires mod_xsendfile module: https://tn123.org/mod_xsendfile/ On Ubuntu may be installed by: apt install libapache2-mod-xsendfile
    • Nginx has a similar X-Accel-Redirect header: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/

    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.

    0 讨论(0)
  • 2020-11-22 04:32

    Configure your server to send the file with the media type application/octet-stream.

    0 讨论(0)
提交回复
热议问题