PHP - 파일 다운로드
안녕하세요, PHP 개발자 지망생 여러분! 오늘은 여러분의 웹사이트에 cool한 기능을 추가할 수 있는 흥미로운 주제에 대해 다룰 예정입니다 - PHP를 사용한 파일 다운로드입니다. 여러분의 친절한 이웃 컴퓨터 선생님이자 저는 이 여정을 단계별로 안내해 드리겠습니다. 그러니 좋아하는 음료를 마시며 편안하게 앉아 코드 작성을 시작해 보세요!
readfile() 함수
PHP에서 파일 다운로드의 핵심에는 readfile()
함수가 있습니다. 이 유용한 작은 함수는 파일을 읽고 그 내용을 출력 버퍼에 쓰는 데 사용하는 도구입니다. 기술적이게 들리시나요? 걱정 마세요 - 함께 설명해 보겠습니다!
기본 사용법
간단한 예제로 시작해 보겠습니다:
<?php
readfile("example.txt");
?>
이 코드 스니пп트에서 readfile()
은 "example.txt"의 내용을 읽고 브라우저에 직접 출력합니다. 마법처럼 파일의 내용이 화면에 나타납니다!
파일 다운로드
이제 흥미로운 부분입니다. readfile()
을 사용하여 파일 다운로드를 유도할 수 있습니다. 보다 완전한 예제를 살펴보겠습니다:
<?php
$file = "myfile.pdf";
if(file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
와우, 이렇게 많은 내용이네요! 하나씩 풀어보겠습니다:
- 다운로드할 파일을 지정합니다 (
$file = "myfile.pdf"
). - 파일이 존재하는지 확인합니다.
- 존재하면 다음과 같은 헤더를 설정합니다:
-
Content-Description
은 브라우저에게 이것이 파일 전송임을 알립니다. -
Content-Type
은 일반 바이너리 파일의 MIME 타입을 설정합니다. -
Content-Disposition
은 브라우저가 파일을 다운로드하도록 유도합니다. - 나머지 헤더는 파일이 캐싱되지 않고 올바르게 처리되도록 합니다.
- 마지막으로
readfile()
을 사용하여 파일 내용을 출력합니다.
일반 파일 타입
다른 파일 타입은 다른 헤더가 필요할 수 있습니다. 다음은 일반 파일 타입과 그에 해당하는 Content-Type 헤더의 표입니다:
파일 타입 | Content-Type 헤더 |
---|---|
application/pdf | |
ZIP | application/zip |
JPEG | image/jpeg |
PNG | image/png |
MP3 | audio/mpeg |
MP4 | video/mp4 |
다운로드 링크 생성
이제 다운로드를 유도하는 방법을 알고 있으므로, 사용자 친화적인 다운로드 링크를 생성해 보겠습니다:
<!DOCTYPE html>
<html>
<body>
<h2>파일 다운로드</h2>
<p><a href="download.php?file=myfile.pdf">PDF 다운로드</a></p>
</body>
</html>
이 HTML에서는 파일 다운로드를 처리할 PHP 스크립트(download.php
)에 대한 링크를 생성합니다. URL에 파일 이름을 매개변수로 전달합니다.
이제 download.php
스크립트를 생성해 보겠습니다:
<?php
if(isset($_GET['file'])) {
$file = $_GET['file'];
$filepath = "uploads/" . $file;
if(file_exists($filepath)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filepath).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filepath));
readfile($filepath);
exit;
} else {
echo "파일을 찾을 수 없습니다.";
}
}
?>
이 스크립트는 다음과 같은 작업을 수행합니다:
- URL에 파일 매개변수가 있는지 확인합니다.
- 파일의 전체 경로를 구성합니다 ( 파일이 "uploads" 디렉토리에 있을 것으로 가정합니다).
- 파일이 존재하면 헤더를 설정하고 다운로드를 유도합니다.
- 파일이 존재하지 않으면 오류 메시지를 표시합니다.
보안 고려 사항
이제 여러분이 떠올리는 것이 있을 겁니다 - "선생님, 이게 좀 위험하지 않나요? 누군가가 부정하게 파일을 다운로드하려고 할 때는요?" 훌륭한 질문입니다! 정말로 그렇습니다. 그래서 보안에 대해 이야기해야 합니다.
파일 경로 검증
사용자 입력을 그대로 신뢰해서는 안 됩니다. 다음은 개선된 다운로드 스크립트입니다:
<?php
if(isset($_GET['file'])) {
$file = basename($_GET['file']);
$filepath = "uploads/" . $file;
// 파일 경로 검증
$realPath = realpath($filepath);
$uploadDir = realpath("uploads/");
if($realPath === false || strpos($realPath, $uploadDir) !== 0) {
die("잘못된 파일 경로입니다.");
}
if(file_exists($filepath)) {
// ... (다운로드 코드의 나머지 부분)
} else {
echo "파일을 찾을 수 없습니다.";
}
}
?>
이 버전에서:
-
basename()
을 사용하여 디렉토리 탐색 시도를 제거합니다. -
realpath()
를 사용하여 파일과 업로드 디렉토리의 실제 경로를 가져옵니다. - 파일의 실제 경로가 업로드 디렉토리 경로로 시작하는지 확인하여 파일이 정해진 디렉토리 밖으로 나가지 않도록 합니다.
결론
이제 여러분은 PHP 파일 다운로드의 세계를 여행하며, readfile()
의 기본 사용법에서 다운로드 링크 생성과 중요한 보안 고려 사항에 이르기까지 다루었습니다. 강력한 권한이 따르는 것은 큰 책임이 따르는 것입니다 - 사용자 입력을 항상 검증하고 파일 다운로드 작업에서 보안을 고려하세요.
이 강의를 여러분이 만큼이나 재미있게 배웠기를 바랍니다. 계속 연습하고 코드를 작성하다 보면, 다양한 cool한 다운로드 기능을 갖춘 놀라운 PHP 애플리케이션을 만들 수 있을 것입니다. 다음 번에는 다시 만납시다, 행복한 코딩을!
Credits: Image by storyset