본문 바로가기

프로그래밍 공부/PHP

PHP - 세션, 파일 업로드 그리고 이미지 축소

세션

세션(session)은 웹 사이트에 대한 접속수를 가리키는 단위이다. 세션 변수를 사용해 페이지를 이동하여도 데이터를 유지하는 방법이 있다.

사용자가 사이트 내에서 행하는 일련의 조작을 하나의 세션으로 센다. 열람한 페이지 수와 관계없이 어느 정도 시간이 지난 후에 조작을 하면 새로운 세션으로 센다. 하나의 세션 안에서 페이지를 표시할 때 웹 브라우저는 웹 서버에 접속하여 HTTP 프로토콜에 따라 요청 헤더와 응답 헤더를 주고받고 페이지가 표기되면 통신을 마친다.

이처럼 항상 웹 서버에 접속한 상태가 아니므로 열람 중인 페이지에서 다음 페이지로 이동하면 이전 페이지 정보를 참조하거나 유지해야 한다. 예시로 홈쇼핑 사이트의 장바구니와 같이 각 회원에 따라 다른 내용을 표시하고 싶을 때도 세션관리를 이용해 같은 사용자가 열람하고 있는 것을 확인하여 저장된 정보를 다른 페이지에도 가지고 다닐 수 있게 한다.

PHP에서 세션 관리

PHP에서 세션을 관리 할때는 세션에 관한 슈퍼 글로벌 변수 $_SESSION에 정보를 넣어두는 것으로 간단하게 세션 관리를 할 수 있다. 세션 ID의 발행, 취득은 자동으로 되기 때문에 문제 없이 할 수 있다. 다만 $_SESSION을 사용하기 전에 session_start(); 함수로 세션의 시작을 선언해야 한다. 새로운 세션을 시작하거나 현재의 세션 ID를 취득하여 세션을 재개한다.

세션 변수에 데이터를 넣어두려면 $_POST 등의 배열처럼 키와 값을 지정한다. 만약 세션 변수에 등록된 키를 제거하려면 session_unregister(); 함수에 키를 지정하여 제거할 수 있다.

세션 변수를 모두 삭제하려면 session_unset(); 함수를 사용한다. 이것을 실행하면 현재 등록된 모든 세션 변수를 초기화 한다. 인수는 따로 지정하지 않고 실행한다. 유효기한을 설정하여 자동으로 종료가 되도록 할 수 있다.

php.ini의 session.cache_expire(); 함수는 설치하면 기본값이 180분으로 설정되어 있다. 이것은 화면에 처음 접속한 후 조작하지 않은 채로 유효기한이 지나면 세션이 소멸하고 다시 조작하면 새로운 세션 ID가 발행이 되게 한다. 또 유효기한은 session_cache_expire(); 함수에서도 분 단위로 설정할 수도 있다.

유효기한을 기다리지 않고 세션 ID와 데이터를 삭제하려면 session_destroy(); 함수를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
    session_start();
    $count = 1;
    if(isset($_SESSION["count"])){
        $count = $_SESSION["count"];
        $count ++;
    }
    $_SESSION["count"= $count;
?>
<html>
<head>
    <title>세션 변수 테스트</title>
    <meta http-eqiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
    세션 변수 테스트<br>
    <br>
    <?php
        if($count == 1){
            ?>
            첫 방문입니다.<br>
            <br>
            세션 변수에 데이터가 없습니다.<br>
            페이지를 참고하세요.<br>
            <?php
        }else{
            ?>
            당신의 방문은 <?=$count?>회째입니다.<br>
            <?php
        }
    ?>
</body>
</html>
cs

위의 코드는 세션을 사용해 카운트를 하는 코드이다. seesion_start(); 함수로 세션을 시작하고 if 조건문으로 데이터가 할당이 되었는지 확인후 $count 변수에 할당하고 $count++로 1씩 증가 시킨다. 이것을 통해 페이지를 새로 고침 할 때 마다 카운트를 한다.

데이터 가지고 다니기

먼저 세션 변수로 수정을 해야한다. 이전에 사용했던 form.html, confirm.php 그리고 view#5.php의 hidden 태그 부분을 세션 변수를 이용해 수정한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>텍스트 송신 테스트</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
    <font size="4">텍스트 송신 테스트</font>
    <form name="form1" method="post" action="confirm.php">
        이름:<br>
        <input type="text" name="name"><br>
        본문:<br>
        <textarea name="introduce" cols="30" rows="5"></textarea><br>
        <input type="submit" value="송신">
        <input type="hidden" name="user_id" value="0001">
    </form>
</body>
</html>
cs

위는 form.html의 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
    session_start();
    $_SESSION["name"= $_POST["name"];
    $_SESSION["introduce"= $_POST["introduce"];
    if(isset($_POST["user_id"])){
        $_SESSION["user_id"= $_POST["user_id"];
    }
?>
<html>
<head>
    <title>PHP 테스트</title>
</head>
<body>
    확인 화면
    <form name="form1" method="post" action="view#5.php">
        <?php
        print "이름:";
        print $_POST["name"];
        print "<br><br>";
        print "본문:<br>";
        print nl2br($_POST["introduce"]);
        ?>
        <br>
        <input type="submit" value="확인" name="confirm">
        <input type="submit" value="돌아가기" name="back">
    </form>
</body>
</html>
cs

위의 confirm.php의 코드에는 먼저 세션 시작 선언을 위한 session_start(); 함수를 사용한다. POST 메서드로 송신된 데이터를 같은 키의 세션 변수에 할당한다. form.html에서 이동한 경우 $_POST["user_id"]가 존재하지만 view.php에서 confirm.php로 이동한 경우 $_POST["user_id"]가 존재하지 않아 오류가 발생하므로 $_POST["user_id"]만 존재하는지 if 조건문을 통해 걸러내야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
    session_start();
?>
<html>
<head>
    <title>PHP 테스트</title>
</head>
<body>
<?php
    if(isset($_POST["confirm"])){
        ?>
        <?php
        // 확인 버튼을 누른 경우
        print $_SESSION["name"]."님으로부터 메세지";
        print "<br><br>";
        print "본문:<br>";
        print nl2br($_SESSION["introduce"]);
        ?>
        <br>
        <br>
        <a href="form.html">한번 더 시험해 보려면 여기를 클릭</a>
        <hr>
        <pre>
            <?php
                print_r($_SESSION);
            ?>
        </pre>
        <hr>
        <?php
    }else if(isset($_POST["back"])){
        // 돌아가기 버튼을 누른경우
        ?>
        <font size="4">텍스트 발송 테스트</font>
        <form name="form1" method="post" action="confirm.php">
            이름:<br>
            <input type="text" name="name" value="<?=$_SESSION["name"]?>">
            <br>
            본문:<br>
            <textarea name="introduce" cols="30" rows="5"><?=$_SESSION["introduce"]?></textarea>
            <br>
            <input type="submit" value="발송">
        </form>
        <?php
    }else{
        // 상기 이외의 경우
        ?>
        오류입니다.<br>
        <a href="form.html">form.html</a>로 돌아갑니다.
        <?php
    }
    ?>    
</body>
</html>
cs

위는 view#5.php 코드로 확인 또는 돌아가기 중 어떤 버튼을 클릭했는지 판단하는 처리를 한다. confirm.php 코드와 마찬가지로 session_start(); 함수로 세션을 시작한다. 송신 버튼을 클릭하면 송신된 데이터 외에에는 데이터가 모두 세션 변수에 할당을 하기 때문에 $_POST["name"]을 $_SESSION["name"]과 같이 변경한다. 세션 변수의 상황을 보기 위해서는 print_r($_SESSION);으로 내용을 표시하게 한다.

파일 업로드

PC에서 파일을 업로드해서 웹 서버에 파일은 전송한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>파일 업로드 테스트</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
    <font size="4">파일 업로드 테스트</font>
    <form name="form1" method="post" action="view#5.php" enctype="multipart/form-data">
        <input type="hidden" name="MAX_FILE_SIZE" value="100000">
        이미지:<input type="file" name="uploadfile"><br>
        설명:<input type="text" name="comment"><br><br>
        <input type="submit" value="파일업로드">
    </form>
</body>
</html>
cs

파일은 송신하려면 위의 코드와 같이 form 태그의 enctype의 속성을 multipart/form-data로 지정해야 한다. hidden 태그의 MAX_FILE_SIZE의 value 속성은 100000으로 지정한다. 이 설정에 따라 용량이 100kb 이내의 파일만 송신할 수 있다. 또한 이 태그는 다음에 나오는 <input type="file">보다 앞에 작성한다. 

파일을 송신하려면 input 태그의 type 속성에 file을 지정한다. 여기에 name 속성은 uploadfile로 지정한다. 파일 설명은 name속성의 comment로 폼에서 함께 송신한다.

파일 받기

파일을 업로드하면 임의의 이름이 붙은 상태로 저장된다. 하지만 아무 처리를 하지 않으면 요청 처리(송신)가 끝나는 순간 파일이 삭제되어 버리기 때문에 삭제되기 전에 파일을 이동시켜야 한다. $_FILES를 사용해 표와 같이 파일 조작에 필요한 각종 정보를 얻을 수 있다.

변수 할당된 데이터
$_FILE["name 속성"]["name"] 업로드된 파일의 이름
$_FILE["name 속성"]["type"] 파일의 MME 형식
$_FILE["name 속성"]["size"] 파일의 크기(바이트 단위)
$_FILE["name 속성"]["tmp_name"] 서버에 저장된 임시 파일명
$_FILE["name 속성"]["error"] 오류코드

파일 이동하기 / 이미지 출력하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<html>
<head>
    <title>PHP 테스트</title>
</head>
<body>
    <?php
        // Windows에 경우
        $file_dir = 'C:\xampp\htdocs\C04\S45\image\\';
        // Mac에 경우
        //$file_dir = '/Applications/XAMPP/xamppfiles/htdocs/C04/S45/images/';
        // Linux에 경우
        //$file_dir = '/opt/lampp/htdocs/C04/S45/images/';
 
        $file_path = $file_dir.$_FILES["uploadfile"]["name"];
        if(move_uploaded_file($_FILES["uploadfile"]["tmp_name"],$file_path)){
            $img_dir = "images/";
            $img_path = $img_dir.$_FILES["uploadfile"]["name"];
            $size = getimagesize($file_path);
            ?>
            파일 업로드를 완료하였습니다.<br>
            <img src="<?=$img_path?>" <?=$size[3]?>><br>
            <b><?=$_POST["comment"]?></b><br>
            <?php
        }else{
            ?>
            정상적으로 업로드 되지 않았습니다.<br>
            <?php
        }
        ?>
</body>
</html>
cs

$file_dir은 파일이 이동할 경로를 설정한다. Windows는 '로 묶인 문자열의 가장 뒤에있는 \를 \\로 입력한다. \라고 마무리하면 '로 문자열이 제대로 닫지 않은 것과 같기 때문이다. $file_path에는 $file_dir과 파일명을 할당한다. 실제 파일명은 $_FILES["uploadfile"]["name"]에 있다. 다음으로 move_uploaded_file(); 함수를 사용해 이동시킨다. move_uploaded_file(임시 파일명, 이동할 곳의 파일명);과 같이 인수를 설정한다.

임시 파일명을 확인후 이동할 곳의 파일명으로 파일을 이동시키는 것이다. 따라서 임시 파일은 삭제되고 move_uploaded_file(); 함수는 TRUE를 리턴해 if 조건문 안의 처리를 하는 것이다. 

이미지를 출력할 때 파일명에 한글을 사용하면 작동하지 않는다, 따라서 영문/숫자로 작성 후 업로드 한다.

이미지 축소

업로드한 이미지를 보기 쉬운 크기로 축소한다. PHP에서 이미지를 조작하려면 GD(Graphics Libaray)를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<html>
<head>
    <title>PHP 테스트</title>
</head>
<body>
    <?php
        $resizeX = 150;
        $thumbnail_name = "tumbnail.jpg";
        // Windows에 경우
        $file_dir = 'C:\xampp\htdocs\C04\S45\image\\';
        // Mac에 경우
        //$file_dir = '/Applications/XAMPP/xamppfiles/htdocs/C04/S45/images/';
        // Linux에 경우
        //$file_dir = '/opt/lampp/htdocs/C04/S45/images/';
        
        $file_path = $file_dir.$_FILES["uploadfile"]["name"];
        $thumbnail_file_path = $file_dir.$thumbnail_name;
        if(move_uploaded_file($_FILES["uploadfile"]["tmp_name"],$file_path)){
            $img_dir = "images/";
            $img_path = $img_dir.$_FILES["uploadfile"]["name"];
            $thumbnail_image_path = $img_dir.$thumbnail_name;
            if(mb_strpos($_FILES['uploadfile']['type'],'jpeg')){
                $gdimg_in = imagecreatefromjpeg($file_path);
                $ix = imagesx($gdimg_in);
                $iy = imagesx($gdimg_in);
                $ox = $resizeX;
                $oy = ($ox * $iy/ $ix;
                $gdimg_out = imagecreatetruecolor($ox,$oy);
                imagecopyresized($gdimg_out,$gdimg_in,0,0,0,0,$ox,$oy,$ix,$iy);
                imagejpeg($gdimg_out,$thumbnail_file_path);
                imagedestroy($gdimg_in);
                imagedestroy($gdimg_out);
                $size = getimagesize($file_path);
                $size2 = getimagesize($thumbnail_file_path); 
                ?>
                파일 올리기를 완료하였습니다.<br>
                <img src="<?=$img_path?>" <?=$size[3]?>>
                <img src="<?=$thumbnail_image_path?>" <?=$size2[3]?>>
                <br>
                <b><?=$_POST["comment"]?></b><br>
                <?php
            }else{
                print "JPGE 형식의 이미지만 업로드하여 주세요.<br>";
            }
            
        }else{
            print "정상적으로 업로드 되지 않았습니다.<br>";            
        }
        ?>
</body>
</html>
cs

이전에 작성했던 view#5.php를 수정하여 업로드한 JPEG 형식의 이미지를 일정한 가로 폭으로 축소 또는 확대 할 수 있도록 한다. imagecreatefromjpeg(); 함수는 지정한 파일을 읽어들여 지정한 변수 $gdimg_in에 이미지를 나타내는 이미지 ID를 할당한다. imagesx(); 함수는 이미지의 가로폭을 imagesy(); 함수는 세로폭을 각각 지정된 변수인 $ix와 $iy에 할당한다.

imagecreatetruecolor(); 함수에 가로와 세로 폭을 지정하여 이미지 ID를 작성하고 $gdimg_out에 할당한다. imagecopyresized(); 함수로 복사와 크기 변경을 할 수 있다. imagejpeg(); 함수로 이미지의 크기를 조절하여 파일을 출력하고 imagedestroy(); 함수로 이용한 메모리를 해제한다.

명칭(또는 함수 이름) 형태 설명
session_start session_star(); 세션을 시작
$_SESSION $_SESSION["키"] = "값"; 세션 변수에 데이터 할당
session_unregister session_unregister("키"); 세션 변수에 등록된 키 제거
session_unset session_unset(); 세션 변수를 모두 제거
session_cache_expire session_cache_expire(분 입력); 유효기한을 설정해 제거
session_destroy session_destroy(); 세션을 제거
$_FILES $_FILES["name"]["name"]; 업로드된 파일의 이름 얻기
  $_FILES["name"]["type"]; 파일의 MME 형식 얻기
  $_FILES["name"]["size"]; 파일의 크기(바이트) 얻기
  $_FILES["name"]["tmp_name"]; 서버에 저장된 임시 파일명 얻기
  $_FILES["name"]["error"]; 오류 코드 얻기
move_uploaded_file move_uploaded_file(임시 파일명, 이동할 곳의 파일명); 파일을 이동
getimagesize getimagesize($변수); $변수에 이미지 정보를 할당
디렉티브(지시어) file_updates 파일업로드 허용 여부 설정
  upload_tmp_dir 파일업로드 임시 저장 디렉터리
  upload_max_filesize 업로드할 데이터의 최대 크기
  post_max_size post로 넘길 데이터의 최대 크기
  memory_limit 메모리 사용량 제한
mb_strpos mb_strpos($변수 또는 대상 문자열, 조건 문자열); $변수, 문자열에 조건 문자열 확인
imagecreatefromjpeg imagecreatefromjpeg($변수); $변수의 파일을 jpeg로 할당
imagesx imagesx($변수); $변수의 가로 폭을 할당
imagesy imagesy($변수); $변수의 세로 폭을 할당
imagecreatetruecolor imagecreatetruecolor($변수 또는 가로, $변수 또는 세로); 가로와 세로를 받아 캔버스 생성
imagecopyresized imagecopyresized($변수,$변수,0,0,0,0, $변수,$변수,$변수,$변수); 복사와 크기 변경
imagejpeg imagejpeg($변수, $변수); jpeg 이미지의 크기 조절 및 출력
imagedestroy imagedestroy($변수); 할당된 메모리를 해제