2016-11-01
보통 페이지의 다운로드는 웹 root 파일 외의 것들도 다운 받을 수 있게 해야 하기 때문에, 아래와 같이 만드는 편이다.
<?php
// GET방식으로 값을 넘겨주기 때문에, base64인코딩과 url인코딩을 같이 써야 한다.

$file = isset($_GET['file'])?$_GET['file']:0; //파일 위치
$fname = isset($_GET['fname'])?$_GET['fname']:0; //파일명

if( !$file || !$fname ) die("Can't access!");

$f = base64_decode(urldecode($file));
$ff = pathinfo( base64_decode(urldecode($fname)) );

if( !file_exists($f) ) die("Can't access!");

switch( $ff['extension'] )
{
    case "pdf": $ctype="application/pdf"; break;
    case "exe": $ctype="application/octet-stream"; break;
    case "zip": $ctype="application/zip"; break;
    case "doc": $ctype="application/msword"; break;
    case "xls": $ctype="application/vnd.ms-excel"; break;
    case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
    case "gif": $ctype="image/gif"; break;
    case "png": $ctype="image/png"; break;
    case "jpeg":
    case "jpg": $ctype="image/jpg"; break;
    default: $ctype="application/force-download";
}

if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
    header("Content-Type: $ctype");
    header('Content-Disposition: attachment; filename="'.$ff['basename'].'"');
    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($f));
}
else
{
    header("Pragma: public"); // required
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false); // required for certain browsers 
    header("Content-Type: $ctype");
    header('Content-Disposition: attachment; filename="'.$ff['basename'].'"');
    header("Content-Transfer-Encoding: binary");
    header('Pragma: no-cache');
    header("Content-Length: ".filesize($f));
}

readfile($f);
?>
이게 파일별로 파일 타입을 지정을 안하면, 특정 파일들은 아예 인식을 못하기도 하기 때문에 파일 타입 명시를 잘 해야 하며, IE인지 크롬인지에 따라서도 조금 달라져야 해서 신경을 좀 써야 한다.