티스토리 뷰

반응형

※ 본 포스팅은 개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있음을 밝힙니다.




PHP와 MySQL로 게시판을 만들던 중


이것저것 알아낸 것들을 짜집어서


파일 업로드와 다운로드, 삭제까지 되는


PHP 페이지를 작성해보았습니다.


좀 다른 점은 업로드 할 때


파일명을 그대로 사용하지 않고


MD5 함수를 사용하여 해시값을 올립니다.


그리고 다운로드 할때도


파일명을 사용하지 않고


DB를 거쳐 기본키를 가지고 다운로드 합니다.





우선 전체적인 웹페이지 구조입니다.




index.php : 첫 화면입니다. 파일 업로드와 등록된 파일 확인이 가능합니다.

upload.php : 파일 업로드시 업로드가 처리되는 php 파일입니다.

download.php : 파일 다운로드시 다운로드가 처리되는 php 파일입니다.

delete.php : 파일 삭제시 실제로 삭제가 처리되는 php 파일입니다.

files : 업로드된 파일이 올라가는 디렉토리 입니다. 권한이 777입니다.



MySQL DB 구조 입니다.




num : 고유 식별번호 느낌의 기본 키 입니다. 

음수가 들어갈일이 없어 unsigned 로 사용했습니다.

auto_increment 로 자동적으로 값이 증감합니다.

name : 파일의 이름이 입력됩니다. varchar 로 255바이트 줬습니다.

hash : 파일이름을 해시 함수로 변경한 값이 입력됩니다. varchar 255

time : datetime 자료형을 사용. 파일이 업로드된 시각이 입력됩니다.

down : 파일 다운로드 횟수 입니다. 음수가 없으므로 unsigned로 사용합니다.






1차 index.php 입니다.

우선 파일 업로드만을 구현합니다.


1
2
3
4
5
6
7
8
9
10
11
<html>
    <meta charset="utf-8"/>
    <title>File Manager</title>
</html>
<body>
    <form action="./upload.php" method="POST" enctype="multipart/form-data" />
        <input type="file" id="file" name="file" required />
        <input type="submit" value="UPLOAD" />
    </form>
</body>
</html>


웹 페이지 인코딩은 utf-8 (유니코드 입니다)

form 테그에서 POST 방식으로 file의 값을 upload.php에 넘겨줍니다.

enctype을 multipart/form-data 로 해주셔야 파일 업로드가 가능합니다.



웹상에 띄워진 화면입니다.





이제 form에서 넘겨주는, 실제로 파일이 업로드되는 upload.php 입니다.


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
<?php
 
    if(!$_FILES['file']['name'])
    {
        echo "<script>alert('업로드 할 파일이 입력되지 않았습니다.');";
        echo "history.back();</script>";
        exit;
    }
    
    if(strlen($_FILES['file']['name']) > 255)
    {
        echo "<script>alert('파일 이름이 너무 깁니다.');";
        echo "history.back();</script>";
        exit;
    }
    
    $date = date("YmdHis", time());
    $dir = "./files/";
    $file_hash = $date.$_FILES['file']['name'];
    $file_hash = md5($file_hash);
    $upfile = $dir.$file_hash;
 
    if(is_uploaded_file($_FILES['file']['tmp_name']))
    {
            if(!move_uploaded_file($_FILES['file']['tmp_name'], $upfile))
            {
                    echo "upload error";
                    exit;
            }
    }
    
    @ $db = new mysqli('DB호스트명''아이디''비밀번호''DB명');
    if(mysqli_connect_errno())
    {
        echo "DB error";
        exit;
    }
    
    $query = "insert into ftp (name, hash, time) 
              values('".$_FILES['file']['name']."', 
              '".$file_hash."', '".$date."')";
    $result = $db->query($query);
    if(!$result)
    {
        echo "DB upload error";
        exit;
    }
    
    $db->close();
    
    echo "<script>alert('업로드 성공');";
    echo "history.back();</script>";
    
?>

if(!$_FILES['file']['name']) : 실제로 업로드할 파일이 입력되었나를 판단합니다.


if(strlen($_FILES['file']['name']) > 255) : 파일제목의 길이를 검사합니다.


$date = date("YmdHis", time()); : date 변수에 time함수에서 값을 뽑아내어 저장합니다.


$dir = "./files/"; : 디렉토리의 경로입니다.


$file_hash = $date.$_FILES['file']['name']; : 이제 해시값을 만들기 위해 file_hash 변수에 'date변수+파일제목'을 입력합니다.(date는 같은 파일제목일 경우 해시값 중복을 피하기 위해)


$file_hash = md5($file_hash); : $file_hash의 값을 md5 함수를 통해 해시화 시킵니다.


$upfile = $dir.$file_hash; : 실제 파일이 업로드 되는 경로입니다.


if(is_uploaded_file($_FILES['file']['tmp_name'])) : 업로드 파일은 임의의 파일명으로 임시로 저장됩니다. 그 파일의 유무를 판단


if(!move_uploaded_file($_FILES['file']['tmp_name'], $upfile)) : 실제 upfile 위치에 임시파일을 복사합니다. 에러발생시 echo문이 실행됩니다.


@ $db = new mysqli('호스트명', '아이디', '비밀번호', 'DB명'); : 업로드된 파일의 정보를 저장하기 위해 DB 연결


if(mysqli_connect_errno()) : DB 연결시 에러 발생하면 이 if문이 실행된다.


$query = "insert into ftp (name, hash, time) values('".$_FILES['file']['name']."', '".$file_hash."', '".$date."')"; : 쿼리문 작성, ftp 테이블 name, hash에 두 원래 파일명과 해시화 된 파일명, date에 업로드된 날짜와 시간을 입력


$result = $db->query($query); : DB에 쿼리를 날리고 그 결과를 result에 저장


if(!$result) : result 값이 NULL이라면 문제가 발생했음으로 if문 실행


$db->close(); : 더 이상 DB를 사용할 일이 없으므로 연결을 해제한다.



index.php, upload.php 두 php파일을 사용하여 업로드가 되는지 확인해 보겠습니다.


파일을 업로드 할 때 실제 파일명이 아닌 해시 값을 파일이름으로 업로드하면


여러가지 보안위협을 줄일 수 있습니다. (웹 쉘 공격 등)




기본 사진 폴더에 있는 Desert.jpg 를 업로드 해보겠습니다.




업로드가 잘 되는 군요.




DB에 잘 올라갔나 확인해 봅시다.



DB에도 잘 올라 간 것 같습니다.



files 디렉토리에도 잘 올라갔나 확인해 봅시다.



files 디렉토리에도 잘 올라 간 것 같습니다.



다음 포스팅에서는 이제 업로드된 파일을 조회하기 위해 index.php 를 수정하고

실제 다운로드가 이루어지는 download.php를 작성해 보겠습니다.






다음 포스팅 링크 입니다.

2. PHP MySQL Hash 함수를 사용한 파일관리 - 파일 조회, 다운로드

3. PHP MySQL Hash 함수를 사용한 파일관리 - 파일 삭



반응형
프로필사진

Yowu (Yu Yongwoo)

흔한 Node.js/Java 백엔드 개발자입니다
Ubuntu와 MacOS 데스크탑 개발 환경을 선호합니다
최근에는 vscode와 IntelliJ를 사용하고 있습니다
vscode에는 neovim, IntelliJ는 ideaVim
개발용 키보드는 역시 HHKB Pro 2 무각입니다
락 밴드에서 드럼을 쳤습니다

최근에 올라온 글
최근에 달린 댓글
«   2024/03   »
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
글 보관함
Total
Today
Yesterday