1

PHP 게시판 제작 - 파일 다운로드

PHP 게시판 제작 - 파일 다운로드

노아의 블로그

    목차
반응형

저번에는 파일을 업로드 했습니다.

이제 업로드 한 파일을 다운로드 해 봅시다.

 

다운로드를 하기 전, 게시판에서 어떤 파일을 올렸는지 확인이 필요합니다.

 

1번 게시글에서는 index.png를 올리고 2번 게시글에서는 myphoto.png를 올렸다고 생각해봅시다.

그러면 그냥 Database Table에 파일 경로 Column을 추가해주면 되죠.

 

하지만 파일이 여러개라면 말이 달라집니다. 

1번 게시글에 index.png, hello.png가 있다고 가정하면

 

테이블에는 

1번 게시글 - index.png

1번 게시글 - hello.png

2번 게시글 - myphoto.png

 

이런 형식으로 올 것입니다.

 

이렇게 된다면 데이터가 중복되어 성능 저하가 발생합니다.

따라서 파일 경로만 있는 테이블을 따로 빼 버리는 거죠.

 

이것이 정규화입니다.

 

첫 번째 그림은 여러개의 파일을 기록하기 위해서 게시판 테이블에 중복이 발생하는 상황입니다.

 

두 번째 그림은 정규화를 통해서 board테이블과 file테이블을 나누어서 중복을 최소화 했습니다.

 

하지만, 테이블이 따로따로인데 어떻게 서로의 테이블에서 자신이 무엇과 연관되어 있는지 알 수 있을까요?

 

그것은 바로 Board의 PK입니다. PK는 Unique 즉 고유합니다. 따라서 file 테이블에 Board의 PK를 넣으면

 

어디 게시글의 파일인지 바로 알 수 있죠. 이것이 왜래 키 입니다. 

이런식으로 말입니다!

 

그리고 조회를 할 때는 

Board 테이블을 조회하면서 file 테이블을 같이 조회하면 됩니다.

결국에는 하나의 번호로 조회를 할 것이니 말이죠. (bno)

 

이제 한번 테이블을 제작 해 봅시다.

 

fid는 역시나 파일의 고유 id고

fname은 파일의 이름입니다.

bno는 board와 연관을 맺습니다.

 

아;; 테이블 이름을 실수로 test라고 명했네요. 괜찮습니다 이럴 경우에는 

Alter로 쉽게 변경할 수 있습니다.

 

이왕 한거 사용자 테이블 이름도 바꾸죠.

OK 좋습니다.

 

이제 파일업로드 처리를 변경해야 합니다.

 

파일 테이블은 bno를 참조하니까 무조건 board(게시글)이 먼저 생성되어야 합니다.

 

그 후에 insert id로 bno를 불러와서 다시 insert 합니다.

if (move_uploaded_file($tempFilePath, $uploadPath)) {
    	$bno = $conn->insert_id;
        $sql = "insert into file(fname,bno) values(?,?)";
        $stmt = $conn->prepare($sql);
	$stmt->bind_param('si',$filename,$bno);
	$stmt->execute();
    } else {
        // 파일 업로드 실패
        echo "Error uploading file.";
    }

코드가 너무 복잡하네요... 가독성이 떨어집니다.

나중에 한번 갈아봅시다.

 

일단. 업로드를 통해서 테스트를 해 봅시다.

test.png라는 파일을 업로드 합니다.

 

작성한 게시글을 들어가니 번호가 120번으로 찍혀있네요.

 

file 테이블을 조회 해 봅시다.

파일 테이블의 bno가 120번으로 잘 insert 되어있습니다!

1번째는 제가 테스트 한 것이고 file id 2번을 보시면 됩니당.

 

이제 다운로드 작업이 필요합니다. 

파일 다운로드 페이지를 제작 해 봅시다.

 

<?php
	$filename = $_GET['file'];
	$file = "../" . $_GET['file'];
	$filesize = filesize( $file);
	header('Pragma: public');
	header('Expires: 0');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Content-Disposition: attachment; filename="' . $filename . '"');
	header('Content-Length: ' . $filesize);
	header('Content-Transfer-Encoding: binary');
	
	$fp = fopen($file, 'rb');
	fpassthru($fp);
	fclose($fp);
	
?>

파일 이름을 받아오고 

../는 파일을 읽을 경로입니다.

 

header은 파일을 업로드 할 때 처럼 똑같습니다.

클라이언트에게 파일을 다운로드 할 준비를 하라 라고 보내는것이죠. 

 

밑에는 진짜 파일을 바이너리 모드로 읽어서 보내는 것 입니다.

 

 

아까 업로드 했던 test.png를 다운로드 받아보겠습니다.

 

 

 

 

하단에 보면 정상적으로 파일이 다운로드 되네요.

파일을 열어보겠습니다..

다운로드가 완료되었습니다.

반응형

'WEB > PHP' 카테고리의 다른 글

Web Shell 찍먹  (0) 2023.06.01
PHP 웹 개발 - 서버 네트워크 세팅  (0) 2023.05.30
PHP 게시판 제작 - 조회수 기능  (0) 2023.05.27