PHP - 파일 다운로드

안녕하세요, PHP 개발자 지망생 여러분! 오늘은 여러분의 웹사이트에 cool한 기능을 추가할 수 있는 흥미로운 주제에 대해 다룰 예정입니다 - PHP를 사용한 파일 다운로드입니다. 여러분의 친절한 이웃 컴퓨터 선생님이자 저는 이 여정을 단계별로 안내해 드리겠습니다. 그러니 좋아하는 음료를 마시며 편안하게 앉아 코드 작성을 시작해 보세요!

PHP - Download File

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

와우, 이렇게 많은 내용이네요! 하나씩 풀어보겠습니다:

  1. 다운로드할 파일을 지정합니다 ($file = "myfile.pdf").
  2. 파일이 존재하는지 확인합니다.
  3. 존재하면 다음과 같은 헤더를 설정합니다:
  • Content-Description은 브라우저에게 이것이 파일 전송임을 알립니다.
  • Content-Type은 일반 바이너리 파일의 MIME 타입을 설정합니다.
  • Content-Disposition은 브라우저가 파일을 다운로드하도록 유도합니다.
  • 나머지 헤더는 파일이 캐싱되지 않고 올바르게 처리되도록 합니다.
  1. 마지막으로 readfile()을 사용하여 파일 내용을 출력합니다.

일반 파일 타입

다른 파일 타입은 다른 헤더가 필요할 수 있습니다. 다음은 일반 파일 타입과 그에 해당하는 Content-Type 헤더의 표입니다:

파일 타입 Content-Type 헤더
PDF 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 "파일을 찾을 수 없습니다.";
}
}
?>

이 스크립트는 다음과 같은 작업을 수행합니다:

  1. URL에 파일 매개변수가 있는지 확인합니다.
  2. 파일의 전체 경로를 구성합니다 ( 파일이 "uploads" 디렉토리에 있을 것으로 가정합니다).
  3. 파일이 존재하면 헤더를 설정하고 다운로드를 유도합니다.
  4. 파일이 존재하지 않으면 오류 메시지를 표시합니다.

보안 고려 사항

이제 여러분이 떠올리는 것이 있을 겁니다 - "선생님, 이게 좀 위험하지 않나요? 누군가가 부정하게 파일을 다운로드하려고 할 때는요?" 훌륭한 질문입니다! 정말로 그렇습니다. 그래서 보안에 대해 이야기해야 합니다.

파일 경로 검증

사용자 입력을 그대로 신뢰해서는 안 됩니다. 다음은 개선된 다운로드 스크립트입니다:

<?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 "파일을 찾을 수 없습니다.";
}
}
?>

이 버전에서:

  1. basename()을 사용하여 디렉토리 탐색 시도를 제거합니다.
  2. realpath()를 사용하여 파일과 업로드 디렉토리의 실제 경로를 가져옵니다.
  3. 파일의 실제 경로가 업로드 디렉토리 경로로 시작하는지 확인하여 파일이 정해진 디렉토리 밖으로 나가지 않도록 합니다.

결론

이제 여러분은 PHP 파일 다운로드의 세계를 여행하며, readfile()의 기본 사용법에서 다운로드 링크 생성과 중요한 보안 고려 사항에 이르기까지 다루었습니다. 강력한 권한이 따르는 것은 큰 책임이 따르는 것입니다 - 사용자 입력을 항상 검증하고 파일 다운로드 작업에서 보안을 고려하세요.

이 강의를 여러분이 만큼이나 재미있게 배웠기를 바랍니다. 계속 연습하고 코드를 작성하다 보면, 다양한 cool한 다운로드 기능을 갖춘 놀라운 PHP 애플리케이션을 만들 수 있을 것입니다. 다음 번에는 다시 만납시다, 행복한 코딩을!

Credits: Image by storyset