에몽이

php 파일 업로드 오류 이유 본문

web/php

php 파일 업로드 오류 이유

ian_hodge 2017. 1. 12. 19:10

개발에서 어려운 부분을 꼽으라면 “프로젝트마다 한 번만 설정하는 것들”을 빼먹을 수 없다.

예컨대 리눅스에 APM 세팅하기, 이클립스에서 Autocomplete 세팅하기, SSL 설치 같은 것인데 막상 매뉴얼을 보면서 차근차근 따라하면 별 것 아닌 문제도 한참 시간이 지나서 다시 하려고 하면 버벅거리는 일이 많다.

PHP 파일 업로드 같은 것을 생각해보면, ini 파일부터 시작해서 의외로 손 대야 할 곳이 많기 때문에 업로드가 동작 안 할 경우에 골치아픈 확인작업을 거쳐야 한다.

특히 “예전에 만들어 놓은 코드를 재사용 해 볼까?”같은 시나리오에서 엉뚱한 실수를 하는 일이 많다. 코드가 같다고 결과가 같지 않은 것이 환경설정의 마법이다.

PHP 파일 업로드에 관한 튜토리얼을 찾으면 대부분 이런 느낌의 튜토리얼이 검색되는데, 코드를 그대로 갖다 쓸 경우에 높은 확률로 move_uploaded_file 함수가 false를 리턴한다.

잔뼈가 굵은 개발자들은 바로 감이 오겠지만 move_uploaded_file 의 두 번째 인자로 파일이 복사될 위치를 지정하게 되는데, 해당 위치에 대한 쓰기 권한을 똑바로 설정하지 않아서 그런 경우가 대부분이다.

특히 대부분 리눅스 웹서버 세팅에서는 쓰기 권한이 필요한 경우에도 디렉토리 권한을 755로 설정하라는 안내가 많기 때문에 move_uploaded_file 함수가 이미지 파일을 옮길 수가 없게 된다.

757로 설정하고 나면 업로드가 잘 된다.

단, 디렉토리에 익명 쓰기 권한을 주고 나면 반드시 확장자 체크 등을 통해서 악성 파일이 업로드되는 것을 막아야 하고 가급적이면 익명 쓰기 권한을 주는 폴더를 최소화해야 한다.

PHP외에도 윈도우즈7 이상부터 파일 쓰기 권한 때문에 문제가 생기는 경우가 은근히 많은데(설치형 게임에서 세이브가 안 된다거나) 저 발상을 떠올리지 못하면 애꿎은 코드만 한참 들볶게 되니 주의해야겠다.


파일을 업로드할 때 에러 핸들링은 간단한 소스에서는 신경쓰지 않는 경우가 있는 것 같다.

사실 급할 때는 그냥 ‘에러 났다’고만 해 주고 어떤 종류의 에러인지까지 소스를 짜는 게 귀찮다.

그럴 때를 위해 그냥 에러 핸들링 소스를 만들었다. 필요할 때 긁으면 될 것이다.

//JSON 형식으로 결과를 리턴한다.
if($_FILES['userfile']['error'] > 0){
	echo '{result: -1, ';
	//오류 타입에 따라 echo 'msg: "오류종류"}';
	switch ($_FILES['userfile']['error']){
	case 1: echo 'msg: "upload_max_filesize 초과"}';break;
	case 2: echo 'msg: "max_file_size 초과"}';break;
	case 3: echo 'msg: "파일이 부분만 업로드됐습니다."}';break;
	case 4: echo 'msg: "파일을 선택해 주세요."}';break;
	case 6: echo 'msg: "임시 폴더가 존재하지 않습니다."}';break;
	case 7: echo 'msg: "임시 폴더에 파일을 쓸 수 없습니다. 퍼미션을 살펴 보세요."}';break;
	case 8: echo 'msg: "확장에 의해 파일 업로드가 중지되었습니다."}';break;
	}
}
//그냥 결과를 화면에 뿌린다.
if($_FILES['userfile']['error'] > 0){
	echo '오류 발생 : ';
	//오류 타입에 따라 echo '오류종류"}';
	switch ($_FILES['userfile']['error']){
	case 1: echo 'upload_max_filesize 초과';break;
	case 2: echo 'max_file_size 초과';break;
	case 3: echo '파일이 부분만 업로드됐습니다.';break;
	case 4: echo '파일을 선택해 주세요.';break;
	case 6: echo '임시 폴더가 존재하지 않습니다.';break;
	case 7: echo '임시 폴더에 파일을 쓸 수 없습니다. 퍼미션을 살펴 보세요.';break;
	case 8: echo '확장에 의해 파일 업로드가 중지되었습니다.';break;
	}
}

JSON 형태는 ajax 파일 업로드에 사용하면 될 것이고, 그냥 화면에 뿌리는 것은 용도를 다양하게 사용할 수 있을 것이다.

위에 보면 오류 코드에 5번이 없다. 내가 빼먹은 게 아니고 원래 없는 것 같다. 이유는 안 찾아봤다.

php.net의 오류 코드 설명을 참고하면 좋을 것이다.

참, 위 에러 핸들링은 PHP 4.3부터 도입된 것 같다. php.net을 참고하면 그렇게 써 있는 듯. 영어 달려서 확신은 못하겠다.

에러 코드 6번은 4.3.10과 5.0.3에서 도입된 것 같고, 7번은 5.1.0에서 도입된 듯.

8번 에러는 5.2.0에서 도입된 것 같은데, 번역이 잘 안 된다. PHP 확장이 업로드를 중지시켰다 정도 되는 것 같은데 뭘까.

- 댓글 기능은 없습니다. 댓글 대신 mail@mytory.net으로 메일 보내 주세요.

'web > php' 카테고리의 다른 글

미리보는 PHP 7 PHP7의 차이점,장점  (0) 2017.04.14
curl  (0) 2017.01.03
우측의 페이지 따라다니는 사이드 바  (0) 2016.11.05
Comments