R's Hacking Daily Log

php - File Upload (2) 본문

PHP

php - File Upload (2)

hanhxx 2023. 7. 25. 15:50

업로드할 파일을 골랐으니 SUBMIT 버튼을 눌렀을 때 서버로 파일을 업로드할 기능을 구현해 보자.

form tag - action 값이 다음 페이지 경로이기 때문에 이번에 작성할 코드의 이름은 file_upload.php가 된다.

 

 

[ file_upload.php ]

<?php
$uploads_dir = './uploads';
$allowed_ext = array('jpg','jpeg','png','gif');

if(!is_dir($uploads_dir)) {
    if(!mkdir($uploads_dir, 0777)) {
        die("fail to make upload directory");
    }
}

if(!isset($_FILES['myfile'])) {
    die("not exist uploaded file");
}

$error = $_FILES['myfile']['error'];
$name = $_FILES['myfile']['name'];

$result = match($error) {
    UPLOAD_ERR_OK => "UPLOAD COMPLETE ($error)",
    UPLOAD_ERR_INI_SIZE => "EXCEED SIZE ($error)",
    UPLOAD_ERR_FORM_SIZE => "EXCEED HTML SIZE($error)",
    UPLOAD_ERR_PARTIAL => "LOADS PARTIAL($error)",
    UPLOAD_ERR_NO_FILE => "FILE NOT EXISTS ($error)",
    UPLOAD_ERR_NO_TMP_DIR => "TEM DIRECOTY NOT EXIST ($error)",
    UPLOAD_ERR_CANT_WRITE => "CAN'T WRITE FILE ON WEB SERVER ($error)",
    UPLOAD_ERR_EXTENSION => "EXTENSION FUNCTION ERROR ($error)"
};

if($error != UPLOAD_ERR_OK) {
    echo $result;
    exit;
}

$upload_file = $uploads_dir.'/'.$name;
$fileinfo = pathinfo($upload_file);
$ext = strtolower($fileinfo['extension']);

$i = 1;

while(is_file($upload_file)) {
    $name = $fileinfo['filename']."-{$i}".$fileinfo['extention'];
    $upload_file = $uploads_dir.'/'.$name;
    $i++;
}

if(!in_array($ext, $allowed_ext)) {
    echo "not confirmed extension";
    exit;
}

if(!move_uploaded_file($_FILES['myfile']['tmp_name'], $upload_file)) {
    echo "file doesn't uploads";
    exit;
}
?>

<html>
    <head>
        <title>FILE Upload</title>
    </head>
    <body>
        <h1>FILE UPLOAD EXAMPLE</h1>
        <h1>file informaiton</h1>
        <ul>
            <li>result : <?php echo $result; ?></li>
            <li>filename : <?php echo $name; ?></li>
            <li>file extension : <?php echo $ext; ?></li>
            <li>file type : <?php echo $_FILES['myfile']['type']; ?></li>
            <li>file size : <?php echo $_FILES['myfile']['size']; ?>byte</li>
        </ul>
        <a href="./file_download.php?file=<?php echo $name; ?>">DOWMLOAD</a>
    </body>
</html>

전체 코드는 위와 같다. 

 

html 코드부터 보면 php 태그로 변숫값을 출력하는 아이템들과

a tag로 파일을 다운로드할 수 있는 링크(= DOMNLOAD)가 설정되어 있다. 

 

 

* a tag - href 속성은 form tag - action처럼 DOWNLOAD문구를 클릭했을 때 이동하게 될 경로를 나타낸다.

* 글로벌 변수 $_FILES는 input tag - type = file로 전달한 파일 정보를 담고 있다. 

 

예를 들어

<input type='file' name='myfile'>

myfile으로 전달한 파일의 오류 코드는 $_FILES['myfile']['error']로 얻을 수 있다.

myfile의 크기는 $_FILES['myfile']['size'], myfile의 이름은 $_FILES['myfile']['name'] ..

 


 

이제는 본격적으로 php 코드를 살펴보자. 

 

$uploads_dir = './uploads';
$allowed_ext = array('jpg','jpeg','png','gif');

변수 uploads_dir & allowed_ext를 정의한다.

uploads_dir는 업로드된 파일이 들어갈 directory 이름으로 사용하고 

allowed_ext는 파일의 허용할 확장자명을 배열로 정의한다. 

 

 

if(!is_dir($uploads_dir)) {
    if(!mkdir($uploads_dir, 0777)) {
        die("fail to make upload directory");
    }
}

if(!isset($_FILES['myfile'])) {
    die("not exist uploaded file");
}

첫 번째 if문에서는 파일을 업로드할 directory가 존재하는지 확인하고 

존재하지 않는 경우 모든 사용자가 접근 가능한 권한으로 directory를 만든다. (mkdir command)

 

두 번째 if문에서는 key-myfile인 파일이 존재하는 지의 여부를 확인한다. 

만약 파일이 선택되지 않았다면 업로드할 파일이 없다는 문구가 출력될 것이다.

 

 

$error = $_FILES['myfile']['error'];
$name = $_FILES['myfile']['name'];

$result = match($error) {
    UPLOAD_ERR_OK => "UPLOAD COMPLETE ($error)",
    UPLOAD_ERR_INI_SIZE => "EXCEED SIZE ($error)",
    UPLOAD_ERR_FORM_SIZE => "EXCEED HTML SIZE($error)",
    UPLOAD_ERR_PARTIAL => "LOADS PARTIAL($error)",
    UPLOAD_ERR_NO_FILE => "FILE NOT EXISTS ($error)",
    UPLOAD_ERR_NO_TMP_DIR => "TEM DIRECOTY NOT EXIST ($error)",
    UPLOAD_ERR_CANT_WRITE => "CAN'T WRITE FILE ON WEB SERVER ($error)",
    UPLOAD_ERR_EXTENSION => "EXTENSION FUNCTION ERROR ($error)"
};

if 문에서 에러가 나지 않았다면 파일을 업로드할 directory가 존재하며, 선택한 파일이 존재한다는 의미이다.

그런 다음 $_FILES에서 업로드한 파일의 에러와 이름값을 가져온다. 

 

match문에서는 error 코드가 무엇이냐에 따라 result 변수 값을 설정해 준다. 

 

 

if($error != UPLOAD_ERR_OK) {
    echo $result;
    exit;
}

$upload_file = $uploads_dir.'/'.$name;
$fileinfo = pathinfo($upload_file);
$ext = strtolower($fileinfo['extension']);

만약 파일이 성공적으로 업로드되지 않았다면 result를 출력하고 코드를 종료하고

파일이 성공적으로 업로드되었다면 변수 upload_file & fileinfo & ext 값을 할당한다. 

 

 

$i = 1;

while(is_file($upload_file)) {
    $name = $fileinfo['filename']."-{$i}".$fileinfo['extention'];
    $upload_file = $uploads_dir.'/'.$name;
    $i++;
}

if(!in_array($ext, $allowed_ext)) {
    echo "not confirmed extension";
    exit;
}

파일의 이름이 중복될 수 있음을 방지하여 i 값을 1부터 증가시키면서 name 값을 설정하고 있다. 

if 문에서는 처음에 정의했던 확장자 배열 안에 업로드한 파일의 확장자가 있는 지의 여부를 확인한다.

 

즉, 허용되는 파일 확장자가 아니라면 문구를 출력하고 코드를 종료시키는 흐름인 것

 

 

if(!move_uploaded_file($_FILES['myfile']['tmp_name'], $upload_file)) {
    echo "file doesn't uploads";
    exit;
}
?>

마지막으로 myfile로 업로드된 파일을 tmp directory에서 설정한 경로로 이동시켜 준다.

이전 글에서도 언급했듯이 move_uploaded_file() 함수를 사용하여 파일을 임시 폴더에서 지정된 경로로 이동시키는 데

이 과정에서 문제가 발생하면 파일을 업로드하지 못했다는 문구를 출력하고 종료한다. 

 

 

php code가 성공적으로 실행되고 난 후,

html 내용이 구현되면 업로드된 파일의 정보를 출력하는 것으로 file_upload.php 내용이 마무리된다. 

 

 

'PHP' 카테고리의 다른 글

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