정상우
hELLO.
정상우
전체 방문자
384,511
오늘
130
어제
1,174
  • hELLO. (121)
    • 컴퓨터과학 (4)
      • 알고리즘 & 자료구조 (4)
    • 언어 & 프레임워크 (63)
      • Go (23)
      • PHP & Laravel (40)
    • 웹 (7)
    • 블록체인 (12)
      • 메인넷 (9)
      • 암호화폐 플랫폼 (3)
    • 포트폴리오 (10)
    • 칼럼 (20)
      • 에세이 (4)
      • 개발자스럽게 살기 (14)
      • 회고 (2)
    • 티스토리 (5)

블로그 메뉴

  • ⚡ 개발자 이력서
  • 🌟 깃허브
  • 💻 강의
  • ✨ 예제코드
  • ⭐ 브런치
  • 태그 클라우드
  • 방명록

공지사항

  • 2차 도메인을 설정했습니다 ✨

인기 글

  • JWT(JSON Web Token)의 개념부⋯
    2021.07.29
    JWT(JSON Web Token)의 개념부⋯
  • 'REST' 를 보다 'RESTful' 하게⋯
    2021.08.14
    'REST' 를 보다 'RESTful' 하게⋯
  • [Laravel] 라라벨 프레임워크⋯
    2021.06.10
    [Laravel] 라라벨 프레임워크⋯
  • 깃허브를 포트폴리오로 쓰려면⋯
    2021.12.25
    깃허브를 포트폴리오로 쓰려면⋯
  • 암호화폐 트레이딩 봇을 만들었⋯
    2021.05.12
    암호화폐 트레이딩 봇을 만들었⋯

태그

  • 개발
  • go
  • 블록체인
  • 프로그래머스
  • 포트폴리오
  • php
  • 코딩테스트
  • 라라벨
  • Algorithm
  • 개발 리뷰

최근 댓글

  • 고맙습니다 ~^^
    정상우
  • 오늘 블로그 만들었는데 검색하⋯
    엥뿌삐
  • 좋은 스킨 정말 감사드립니다.⋯
    이태홍
  • 고맙습니다 ㅎㅎ
    정상우
  • 제가 원하던 최고의 스킨입니다⋯
    _HEON

최근 글

  • 빠르게 성장하는 개발자의 세⋯
    2022.06.08
    빠르게 성장하는 개발자의 세⋯
  • 개발자와 엔지니어, 그 사이에서
    2022.05.10
    개발자와 엔지니어, 그 사이에서
  • 아임포트(Iamport)로 결제기능⋯
    2022.04.03
    아임포트(Iamport)로 결제기능⋯
  • 아임포트(Iamport)로 결제기능⋯
    2022.04.01
    아임포트(Iamport)로 결제기능⋯
  • [Laravel] 카페24 호스팅에 라⋯
    2022.03.29
    [Laravel] 카페24 호스팅에 라⋯

티스토리

hELLO · Designed By 정상우.
정상우

hELLO.

언어 & 프레임워크/PHP & Laravel

PHP: 파일 업로드와 다운로드

2020. 6. 10. 22:00

파일 업로드

파일을 업로드하는 방법은 아주 간단하다. 따로 모듈을 사용할 필요 없이 자체 내장 함수만으로도 업로드를 처리할 수 있다. 물론, 이부분도 보안을 처리해주어야 할 것들이 있다. 할 일이 그렇게 많지는 않으므로 같이 언급하고자 한다.

폼

아래의 폼은 파일을 업로드 위해 작성한 폼이다 속성 부분에 있는 entype="multipart/form-data" 부분이 있어야 하므로 폼을 작성할 때는 이점을 꼭 확인해야한다. POST 요청을 하는 것도 잊지 말자.

<form action="/" method='POST' enctype="multipart/form-data">
    <input type="file" name="uploads">
    <input type="submit">
</form>

$_FILES

이 배열은 슈퍼 글로벌 변수로써 프론트에서 요청한 파일 정보가 담겨있으며, 키값은 폼에서 보이는 것처럼 uploads 이다.  이것은 2차원 배열이기 때문에 해당 값안에는 또 다시 배열이 담겨있으며 파일의 이름과 같은 정보가 담겨있다.

$file = $_FILES['uploads'];

파일 업로드

is_uploaded_file(), move_uploaded_file() 함수를 사용하면 파일 업로드를 진행할 수 있다. 이 함수가 무엇을 하는지는 이름만 봐도 알 수 있을 것이라 생각한다. 파라매터에 대한 설명은 간단하기에 생략하겠지만, is_uploaded_file() 로 파일이 업로드 되었는지를 체크하고, move_uploaded_file() 로 파일을 업로드한다.

if (is_uploaded_file($file['tmp_name'])) {
    move_uploaded_file($file['tmp_name'], '__FILE_FULL_PATH__');
}

PHP는 파일 업로드가 요청되면 서버 내부에 임시 파일을 만들게 되는데, 그 경로가 바로 tmp_name 키에 담겨있다. 따라서 해당 파일을 업로드해도 된다고 검증이 완료되면, move_uploaded_file() 을 통해서 실제로 업로드할 폴더로 이동시키는 것이다.

파일 다운로드

파일을 다운로드하는 코드는 그다지 설명할 내용이 많이 없는데, 아래의 코드를 보자. 헤더의 경우는 그냥 넘겨도 가능하지만, 사실 눈여겨 보아야 할 것은 따로 있다. 바로 basename() 함수다. 파일을 다운로드하는 것은 Document Root 의 바깥 폴더에 있는 것도 다운로드 가능하다는 것을 잊어서는 안 된다.

 

참고로 readfile() 함수는 별도의 출력없이도 Output Stream 으로 내용을 내보내준다.

if (file_exists($filepath)) {
    header('Content-type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . basename($filepath));
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . filesize($filepath));

    readfile($filepath);
}

보안

basename(string): string

이 함수는 파일의 이름을 포함한 경로를 받게 되면, 파일의 이름을 얻어오는 아주 단순한 함수다. 그런데, 보안의 측면에서 볼때 이것을 사용하게 되면 파일 다운로드 취약점을 어느 정도는 막을 수 있다.

 

파일 다운로드 취약점은 ../../passwd 와 같은 경로가 외부에서 다운로드 요청 파라매터로 들어온 경우, 앞에 ../../ 은 날려주기 때문에 상당히 안전하다. 따라서 해당 함수를 통해 막아줄 필요가 있다.

string $path 파일 경로

정규 표현식

다운로드의 경우 대부분은 사용자가 다운로드할 파일을 지정해줄 수 있다. 여기서 파일의 이름을 조작하거나, 보안상 위험한 파일의 다운로드를 요청할 수 있는데, 그럴 때 필요한 것이 다운로드 하려는 패치 파라매터의 정보에 대해 임의의 정규 표현식을 적용시켜 검증하는 것이다.

if (preg_match('/\d_\d{10}_[0-9a-z]{32}/', $path)) {
    // ...
}

확장자

확장자에 대한 검증은 파일 업로드와 다운로드에서 둘 다 처리해야 한다. 허용하려는 파일 확장자를 미리 정의한다음 단순히 검증을 해주면 된다. 보안을 처리하는 행위는 간단해보일지라도 모르면 당하기 쉽다.

$accepts = ['jpg'];

$fileinfo =  new \SplFileInfo($file['name']);
if (in_array(strtolower($fileinfo->getExtension()), $accepts)) {
    // ....
}

php.ini

php.ini 설정파일에 보면 File Uploads 와 관련된 보안 설정이 있어서 파일 업로드 자체를 끄거나 최대 요청 파일 갯수, 허용 파일크기 제한 등을 걸어줄 수 있다. 따라서 어플리케이션에서 파일과 관련된 기능을 제공한다면 이것들도 참고해서 설정할 수 있을 것이다. file_uploads, upload_max_filesize, max_file_uploads 설정이다.

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Whether to allow HTTP file uploads.
; http://php.net/file-uploads
file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
; http://php.net/upload-tmp-dir
;upload_tmp_dir =

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 2M

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

더 읽을거리

https://www.inflearn.com/course/php7-reboot

https://www.inflearn.com/course/php7-oop

PHP 카테고리 목차 및 문서 정리

2020년, PHP 언어가 가지는 의미

https://www.php.net/manual/en/

    '언어 & 프레임워크/PHP & Laravel' 카테고리의 다른 글
    • PHP: 의존성 관리자 — Composer
    • PHP: MVC(Model, View, Controller)
    • PHP: 데이터베이스 (MySQLi, PDO)
    • PHP: 쿠키와 세션
    php, 보안, 파일, 파일 다운로드, 파일 업로드
    정상우
    정상우
    과거의 배움으로 현재를 바꾸고 미래를 만듭니다. #25+2살 #INFJ #개발자 #브런치작가
    댓글쓰기
    다음 글
    PHP: MVC(Model, View, Controller)
    이전 글
    PHP: 데이터베이스 (MySQLi, PDO)
    • 이전
    • 1
    • ···
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • ···
    • 40
    • 다음

    티스토리툴바