R's Hacking Daily Log

php - File Upload (3) 본문

PHP

php - File Upload (3)

hanhxx 2023. 7. 26. 13:05

마지막으로 DOWNLOAD를 클릭했을 때, 파일을 다운로드하는 기능을 구현해 보자.

 

 

[ file_download.php ]

<?php
$filename = $_GET['file'];
$filepath = $_SERVER['DOCUMENT_ROOT'].'/myapp/ch08/uploads/'.$filename;

if(!is_file($filepath) || !file_exists($filepath)) {
    echo 'file not exist';
    exit;
}

if(preg_match("/msie/i", $_SERVER['HTTP_USER_AGENT']) && preg_match("/5\.5/", $_SERVER['HTTP_USER_AGENT'])) {
    header("content-type: doesn/matter");
    header("content-length: ".$filesize("$filepath"));
    header("content-disposition: attachment; filename=\"$filename\"");
    header("content-transfer-encoding: binary");
} else {
    header("content-type: file/unknown");
    header("content-length: ".filesize("$filepath"));
    header("content-disposition: attachment; filename=\"$filename\"");
    header("content-description: php generated data");
}

header("pragma: no-cache");
header("expires: 0");

$fp = fopen($filepath, 'rb');

while(!feof($fp)) {
    echo fread($fp, 100*1024);
}

fclose($fp);

전체 코드는 위와 같다. file_upload.php에서 DOWNLOAD에는 a tag로 링크가 걸려있는 데

경로(href attribute)를 보면 

 

<a href="./file_download.php?file=<?php echo $name; ?>">DOWNLOAD</a>

file_download.php로 file parameter를 전달한다. 

전달되는 값은 information에 기재된 filename 값이며 url 형태로 href가 설정되어 있기 때문에

$_POST가 아닌 $_GET에 저장된다. 

 

 

$filename = $_GET['file'];
$filepath = $_SERVER['DOCUMENT_ROOT'].'/myapp/ch08/uploads/'.$filename;

따라서 글로벌 변수 GET에서 key가 file인 값을 filename 변수에 할당하는 것이다.

변수 filepath는 파일이 업로드되어 있는 서버에서의 위치를 가리킨다.

 

 

if(!is_file($filepath) || !file_exists($filepath)) {
    echo 'file not exist';
    exit;
}

다운로드할 파일이 존재하는지의 여부를 확인하기 위해 is_file & file_exists 함수를 사용하고 있다.

 

is_file 함수는 인수로 전달한 파일이 존재하는 지의 여부를 확인하고 

file_exists 함수는 인수로 전달한 파일 OR 폴더(directory)가 존재하는 지 확인하는 함수이다.

 

만약 두 함수의 결과값 중 하나라도 False라면 ! 연산자에 의해 True로 값이 반전되기 때문에 

if문에 작성된 내용이 실행된다. 

 

 

if(preg_match("/msie/i", $_SERVER['HTTP_USER_AGENT']) && preg_match("/5\.5/", $_SERVER['HTTP_USER_AGENT'])) {
    header("content-type: doesn/matter");
    header("content-length: ".$filesize("$filepath"));
    header("content-disposition: attachment; filename=\"$filename\"");
    header("content-transfer-encoding: binary");
} else {
    header("content-type: file/unknown");
    header("content-length: ".filesize("$filepath"));
    header("content-disposition: attachment; filename=\"$filename\"");
    header("content-description: php generated data");
}

header("pragma: no-cache");
header("expires: 0");

파일의 여부가 확인되었다면 브라우저를 체크하고 이런저런 header 값을 설정해 준다.

이때 content-diposition에 작성된 filename 값이 다운로드할 파일명을 가리킨다. 

 

 

$fp = fopen($filepath, 'rb');

while(!feof($fp)) {
    echo fread($fp, 100*1024);
}

fclose($fp);

마지막으로 'rb' 읽기 모드로 파일을 열어서 설정된 사이즈만큼 파일 내용을 읽어 들이면 된다.

 

fopen 함수로 모드를 설정해 파일을 열어주고 feof() 함수로 파일 포인터가 가리키는 지점이 파일의 끝인지를 

확인하면서 "끝이 아닌 동안 fread 함수로 지정된 크기(100*1024)만큼 내용을 읽어"들인다. 

 

파일에 대한 작업이 끝났다면 fclose 함수로 파일을 닫아주어야 한다. 

 

 

다운로드 버튼에 마우스를 드래그하면 왼측 하단에 url이 뜨는 걸 볼 수 있다.

filename이 0002.png인 것과 비교해 보면 file parameter 값이 업로드된 파일명이라는 걸 알 수 있다.

 

 

다운로드 버튼을 클릭하면 file_download.php 코드가 실행되면서

해당 파일이 열리고 내용을 읽어오고 닫히는 과정을 통해 (fopen → fread → fclose)

성공적으로 파일이 다운된 걸 확인할 수 있다!!

 


 

지금까지 file_upload_form, file_upload, file_download에 걸쳐 

php에서 파일을 업로드하고 다운로드하는 과정에 대해 알아보았다.

 

file을 업로드하기 위해서는 input tag의 file type을 활용했고

monve_uploaded_file() 함수로 임시 폴더에서 지정된 경로로 파일을 업로드했다.

 

마지막으로 download 버튼을 눌렀을 때,

브라우저 종류에 알맞게 header를 설정하여 fopen & fread & fclose 함수로 파일을 다운로드할 수 있었다.

 

흔히 사용되는 기능인만큼 큰 흐름을 이해한다면 입맛대로 구현해 보는 데에 큰 도움이 될 것이다!! :)

'PHP' 카테고리의 다른 글

php - Mini Project 1 - (2)  (1) 2023.07.31
php - Mini Project 1 - (1)  (0) 2023.07.30
php - File Upload (2)  (0) 2023.07.25
php - File Upload (1)  (0) 2023.07.25
php - HTML Form으로 데이터 전송하기 (2)  (0) 2023.07.24
Comments