HTML5 에서 multiple 이라는 요소가 추가되었습니다. 이 부분은 이전에 설명된 부분이지만 추가적인 설명을 해보겠습니다.


이것을 이용하면 자바스크립트를 사용하지 않고도 드래그로 파일을 여러 개 선택하여 한번에 파일을 전송할 수 있게 됩니다.


name 요소에 upfile[] 를 사용한 점에 주목해야 합니다. 형식은 다음과 같습니다.


 <input type="file" name="upfile[]" multiple>


ex.1)

 <form enctype="multipart/form-data" action="" method="POST"> 
 <input type="file" name="upfile[]" value="" multiple > 
 <input type="submit" value="전송" /> 
 </form> 

 <?php 
 print_r
($_FILES); 
 /* 
 출력: 
 Array 
 ( 
    [upfile] => Array 
        ( 
            [name] => Array 
                ( 
                    [0] => logo_Image.jpg 
                    [1] => urlshort.zip 
                ) 

            [type] => Array 
                ( 
                    [0] => image/jpeg 
                    [1] => application/x-zip-compressed 
                ) 

            [tmp_name] => Array 
                ( 
                    [0] => C:\Windows\Temp\php1E58.tmp 
                    [1] => C:\Windows\Temp\php1E59.tmp 
                ) 

            [error] => Array 
                ( 
                    [0] => 0 
                    [1] => 0 
                ) 

            [size] => Array 
                ( 
                    [0] => 22150 
                    [1] => 1065 
                ) 

        ) 

 ) 
 */ 
 ?>


multiple 요소에 mime-type 요소를 같이 사용할 수 있습니다. 예를 들면 이미지만 업로드 허용하던지 아니면 zip 파일만 업로드하게 할 수 있습니다. 형식은 다음과 같습니다.


 <input type="file" name="upfile[]" value="" multiple  accept="image/*">

ex.2)

 <form enctype="multipart/form-data" action="" method="POST"> 
 <input type="file" name="upfile[]" value="" multiple  accept="image/*"

 <input type="submit" value="전송" /> 
 </form> 


관련 글: [HTML5] FileAPI 를 이용한 다중 파일 업로드 구현


블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요


파일 업로드시 php 나 html 등 위험한 파일은 보통 제한하게 됩니다. 그래서 다양한 방법으로 허용가능 파일인지 체크 스크립트를 작성해 주는데, 문제는 잘못된 체크방법으로 개발자도 모르는 우회하여 파일을 업로드됩니다.

예제 (ex #1
 <?php 
 $filename 
"test.php."
;
 $ext array_pop(explode("."strtolower($filename
)));

 if(@ereg($ext"php|php3|php4|htm|inc|html")){
        echo 
"죄송합니다. php, html 파일은 업로드가 제한됩니다."
;
 }
 ?>

아무 문제가 없어 보이지만, 실은 php. 나 htm. gif. 등 모두 실행 가능한 파일임을 알아 둘 필요가 있습니다. 그러므로 다음 같이 한번더 체크해서 공격자가 우회하지 못하게 해주는게 좋습니다.

예제 (ex #2
 <?php 
 $filename 
"test.gif.bmp.php."
;
 $ext explode("."strtolower($filename
));

 $cnt count($ext)-1
;
 if(
$ext[$cnt] === ""
){
    if(@
ereg($ext[$cnt-1], "php|php3|php4|htm|inc|html"
)){
        echo 
"죄송합니다. php, html 파일은 업로드가 제한됩니다."
;
    }
 } else if(@
ereg($ext[$cnt], "php|php3|php4|htm|inc|html"
)){
        echo 
"죄송합니다. php, html 파일은 업로드가 제한됩니다."
;
 }
 ?>
블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

  • Favicon of http://Null BlogIcon torrious 2011.11.30 03:01  댓글주소  수정/삭제  댓글쓰기

    지나가다 오타가 있어 적고 갑니다.

    if($ext[$cnt] === "";){
    if(@ereg($ext[$cnt-1], "php|php3|php4|htm|inc|html";)){
    echo "죄송합니다. php, html 파일은 업로드가 제한됩니다.";
    }
    } else if(@ereg($ext[$cnt], "php|php3|php4|htm|inc|html";){
    echo "죄송합니다. php, html 파일은 업로드가 제한됩니다.";
    }


    에서
    else if(@ereg($ext[$cnt], "php|php3|php4|htm|inc|html";){ 를

    else if(@ereg($ext[$cnt], "php|php3|php4|htm|inc|html";)){ 로 정정 바랍니다.

    괄호가 안닫혔더라구요

  • Favicon of https://blog.habonyphp.com BlogIcon 하보니 2011.11.30 19:36 신고  댓글주소  수정/삭제  댓글쓰기

    ㅎㅎ 확인해보니 닫질 않았네요
    조은 지적 감솨합니당.... 수정되었습니다.

pclzip 라이브러리는 http://www.phpconcept.net 에서 제공하는 무료 소프트웨어로 GNU/LGP를 따릅니다. 먼저,

파일을 다운받아 예제에 작성된 위치에 include 하여 클레스를 호출하면 원하는 작업을 할 수 있습니다.

압축파일 생성, 수정, 삭제시 반환되는 배열은 다음 표와 같습니다.

 

 배열
 filename 원본 파일(또는 폴더)
 stored_filename 변경된 파일(또는 폴더)
 size 원본 크기
 compressed_size 압축된 크기
 mtime 수정시간
 comment
 folder 폴더이면 "1" 반환
 index
 status 성공하면 "ok"반환
 crc

Zip 압축파일 만들기

파일(또는 폴더)를 압축해 보겠습니다.

예제 (ex #1

 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);

 
// $create = new PclZip("생성할 압축파일 이름");
 // PclZip 객체에 test.zip 압축파일로 만듭니다.
 
$zipfile = new PclZip('test.zip'
);

 
// $create->create("파일 or 디렉토리");
 // $data에 하나의 파일(또는 폴더)이거나 배열형 파일(또는 폴더)가 올 수 있습니다. 
 // test.php 파일과 www 폴더를 현제 경로에 test.zip 파일로 압축하겠습니다.
 
$data 
= array();
 
$data = array("test.php""www"
);
 
$create $zipfile->create($data
);


 echo 
"<pre>\n"
;
 
print_r($create
);

 
?>

다음은
www 폴더를 압축하되 test폴더를 만들어 압축해 보겠습니다.

예제 (ex #2
 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);

 
// $create = new PclZip("생성할 압축파일 이름");
 // PclZip 객체에 test.zip 압축파일로 만듭니다.
 
$zipfile = new PclZip('test.zip'
);

 
// $create->create("파일 or 디렉토리", );
 // $data에 하나의 파일(또는 폴더)이거나 배열형 파일(또는 폴더)가 올 수 있습니다. 
 // www 폴더를 현제 경로에 test.zip 파일로 압축하겠습니다.
 // 그리고 $data 뒤에 test 입력하고, 압축하면 stored_filename 변수에
 // 이동경로를 확인할 수 있습니다,
 
$data "www"
;
 
$create $zipfile->create($data"test"
);


 echo 
"<pre>\n"
;
 
print_r($create
);

 
?>


Zip
압축파일 추가


압축파일에 새로운 파일을 추가하거나 해당 압축파일이 없으면 새로 압축파일을 만듭니다.

예제 (ex #3

 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);

 
// PclZip 객체를 생성합니다.
 // 추가할 압축파일를 선택합니다. 
 // test.zip 에 파일을 추가하겠습니다.
 
$zipfile = new PclZip('test.zip'
); 

 
// $data에 추가할 파일을 배열로 지정합니다.
 // $data에 하나의 파일(또는 폴더)이거나 배열형 파일(또는 폴더)가 올 수 있습니다. 
 
$data = array("index.gif","test.gif"
);
 
$add $zipfile->add($data
);


 echo 
"<pre>"
;
 
print_r($add
);

 
?>
 

Zip 압축파일내 엔트리 얻기


다음은 압축파일내 엔트리, 즉 파일 목록을 가져 오겠습니다. 반환파일에 대한 정보를 배열로 반환하기 때문에 적절히 수정해서 사용하면 됩니다.

예제 (ex #4

 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);

 
// PclZip 객체를 생성합니다.
 // 목록을 가져올 파일을 선택합니다.
 
$zipfile = new PclZip('test.zip'
); 

 
// 엔트리 얻기
 
$list $zipfile->listContent
();


 echo 
"<pre>"
;
 
print_r($list
);
 
/*
 결과:
 Array
 (
    [0] => Array
        (
            [filename] => test/
            [stored_filename] => test/
            [size] => 0
            [compressed_size] => 0
            [mtime] => 1310291714
            [comment] =>
            [folder] => 1
            [index] => 0
            [status] => ok
            [crc] => 0
        )
    [1] => Array
        (
            [filename] => test/lib/
            [stored_filename] => test/lib/
            [size] => 0
            [compressed_size] => 0
            [mtime] => 1310291392
            [comment] =>
            [folder] => 1
            [index] => 1
            [status] => ok
            [crc] => 0
        )
        ...
 }
 */
 
?> 


Zip 압축파일 해제


압축파일을 현재 디렉토리에 압축해제 해보겠습니다.

예제 (ex #5

 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);

 
// PclZip 객체를 생성합니다.
 //$객체 = new PclZip("해제할 압축파일 이름");
 
$zipfile = new PclZip('test.zip'
); 

 
// 참고로 $extract 변수를 정의하지 않아도 압축해제는 가능합니다.
 
$extract $zipfile->extract
(); 


 echo 
"<pre>"
;
 
print_r($extract
);

 
?>

다음은 다른 디렉토리에 압축파일을 해제하도록 하겠습니다.

예제 (ex #6

 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);

 
// PclZip 객체를 생성합니다.
 //$객체 = new PclZip("해제할 압축파일 이름");
 
$zipfile = new PclZip('test.zip'
); 

 
// 압축파일을 habony 폴더에 압축해제합니다.
 
$extract $zipfile->extract(PCLZIP_OPT_PATH'./habony/'
); 


 echo 
"<pre>"
;
 
print_r($extract
);

 
?>

Zip 압축파일내 파일삭제


이제 부분적으로 압축파일내 파일을 삭제해 보겠습니다.

예제 (ex #7

 <?php
 
// pcl lib 경로 설정
 
include('pclzip.lib.php'
);


 
// PclZip 객체를 생성합니다.
 // 압축파일을 선택합니다.
 
$zipfile = new PclZip('test.zip'
); 

 
// test.gif 를 삭제하겠습니다.
 // 하나의 파일(또는 폴더)이거나 배열형 파일(또는 폴더)가 올 수 있습니다. 
 
$delete $zipfile->delete(PCLZIP_OPT_BY_NAME,"test.gif"
);


 echo 
"<pre>"
;
 
print_r($delete
);

 
?>

블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

string strstr ( string $haystack , mixed $needle [, bool $before_needle ] ) (PHP 4, PHP 5)

$before_needle 은 5.3부터 사용가능하며, 반환값은 매치되는 문자열을 반환합니다. 대소문자 구분없이 문자열을 찾고자 한다면, stristr 함수를 사용하면 됩니다.

예제 (ex #1
 <?php
 $email  
'name@test.com'
;
 $domain strstr($email'@'
);
 echo 
$domain
// 결과: @test.com

 // PHP 5.3.0 부터
 $user 
strstr($email'@', true);
 echo $user// 결과: name
 ?>

파일 확장자 php. 도 웹에서 실행가능한 파일로 인식하기 때문에 php?  php.  ?php 를 제한할 필요가 있습니다.

예제 (ex #2
 <?php 
 $file  
'test.gif.bmp.php.';  
 // 대소문자 구분을 위해 stristr 함수를 사용.
 
$ext stristr($file'.'); 
 echo 
$ext// 결과: .gif.bmp.php. 

 
if(eregi("[php|htm|inc]"$ext)){
       echo 
"제한되는 확장자가 포함되어 있습니다.";
 } else {
       echo 
"업로드 가능합니다.";
 } 
 // 결과: 제한되는 확장자가 포함되어 있습니다. 
 
?>

다음은 stripos 를 이용한 처음 문자열을 찾습니다.

예제 (ex #3
 <?php 
 
function userStrstr($haystack$needle
) { 
    
$pos stripos($haystack$needle
); 
    if (
is_int($pos
)) { 
        return 
substr($haystack$pos strlen($needle
)); 
    }  
    return false;
 }  




 $email 'name@test.com'
 
$domain userStrstr($email'@'
); 
 echo 
$domain
// 결과: test.com 
 
?>
블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

이 기능은 업,다운로드 중 다른 작업을 가능하게 해주는 진보된 기능입니다. 사용 방법은 이전 함수와 크게 다르지 않으니 어렵지 않습니다.

다음은 B 호스트에서 로컬로 다운로드합니다.

예재(ex #1

  <?php 
 
// ftp는 상대경로, 절대경로가 허용되지 않으며,
 // 보통 public_html, www, html 로 시작합니다.
 // public_html/userid 에서 자료를 가져 온다면,
 // ftp 경로는 "public_html/userid/파일" 이 됩니다.

 // B 호스트 정보
 
$ftp_server "호스트 혹은 ip주소"

 
$ftp_user_name "접속 아이디"

 
$ftp_user_pass "접속 패스워드"


 
// B 호스트 접속
 
$conn_id ftp_connect($ftp_server
); 

 
// B 호스트 로그인 
 
$login_result ftp_login($conn_id$ftp_user_name$ftp_user_pass
); 

 
// 원격으로 B 호스트에서 다운로드합니다.
 // 로컬에 저장할 파일명, 필요시 경로도 같이 작성해 줍니다. 
 
$file 'test_body.php'

 
$fp fopen($file'w'
); 

 
// 원격으로 public_html/userid/test.php 파일을 가져옵니다.
 
$ret ftp_nb_fget($conn_id$fp'public_html/userid/test.php'FTP_BINARY
); 
 
$i 1
;
 while (
$ret == FTP_MOREDATA
) { 

   
// 다운로드중 다른 작업을 작성합니다.
   
echo "${i} \n"
;
   
$i
++;
   
$ret ftp_nb_continue($conn_id
); 
 } 
 if (
$ret != FTP_FINISHED
) { 
      echo 
"다운로드 중 에러가 발생하였습니다."

      exit(
1
); 
 } 
 

 
ftp_close($conn_id
); 
 
fclose($fp
); 
 
?>


다음은 로컬파일을 B 호스트로 업로드합니다.

예제(ex #2

  <?php 
 
// ftp는 상대경로, 절대경로가 허용되지 않으며,
 // 보통 public_html, www, html 로 시작합니다.
 // public_html/userid 에 자료를 저장한다면,
 // ftp 경로는 "public_html/userid/파일" 이 됩니다.

 // B 호스트 정보
 
$ftp_server "호스트 혹은 ip주소"

 
$ftp_user_name "접속 아이디"

 
$ftp_user_pass "접속 패스워드"


 
// B 호스트 접속
 
$conn_id ftp_connect($ftp_server
); 

 
// B 호스트 로그인 
 
$login_result ftp_login($conn_id$ftp_user_name$ftp_user_pass
); 

 
// 원격으로 전송할 파일
 // 필요시 사용자 업로드 파일을 B 호스트로 전송시
 // $_FILES['userfile']['tmp_name'] 으로 작성하면 됩니다.
 
$file 'test.php'

 
$fp fopen($file'r'
); 

 
// 원격으로 public_html/userid/test.php 파일 이름으로 저장합니다.
 
$ret ftp_nb_fput($conn_id'public_html/userid/test.php'$fpFTP_BINARY
); 
 
$i 1
;
 while (
$ret == FTP_MOREDATA
) { 

   
// 업로드중 다른 작업을 작성합니다.
   
echo "${i} \n"
;
   
$i
++;
   
$ret ftp_nb_continue($conn_id
); 
 } 
 if (
$ret != FTP_FINISHED
) { 
      echo 
"업로드중 에러가 발생하였습니다."

      exit(
1
); 
 } 

 
ftp_close($conn_id
); 
 
fclose($fp
); 
 
?>


다음은 원격 업로드 이어전송하기 및 프로그레스 입니다.

예제(ex #3

  <?php
 ob_end_flush
();
 
$remote_file 'remote.txt'
;
 
$local_file 'local.txt'
;

 
$fp fopen($local_file'r'
);

 
$conn_id ftp_connect($ftp_server
);
 
$login_result ftp_login($conn_id$ftp_user_name$ftp_user_pass
);

 
$ret ftp_nb_fput($conn_id$remote_file$fpFTP_BINARY
);
 while (
$ret == FTP_MOREDATA
) {
     
// 업로드 중 리소스 소멸시 재연결합니다.
     
if(!isset($conn_id2
)) {
         
$conn_id2 ftp_connect($ftp_server
);
         
$login_result2 ftp_login($conn_id2$ftp_user_name$ftp_user_pass
);
      }
        
      
// 전송된 파일 크기를 측정합니다.
      
if(isset($conn_id2
)) {
          
clearstatcache
();
          
$remote_file_size ftp_size($conn_id2$remote_file
);
      }

      
// 프로그레스
      
$local_file_size  filesize($local_file
);
      if (isset(
$remote_file_size) && $remote_file_size 
){
          
$i = ($remote_file_size/$local_file_size)*100
;
          
printf("%d%% uploaded<br />\n"$i
);
          
flush
();
      }  
       
$ret ftp_nb_continue($conn_id
);
 }

 if (
$ret != FTP_FINISHED
) {
     print(
"There was an error uploading the file...<br />\n"
);
     exit(
1
);
 }
 else {
     print(
"ok!<br />\n"
);
 }

 
ftp_close($conn_id
); 

 
fclose($fp
);
 
?> 

블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

php ftp에는 다양한 기능을 제공합니다. 그중 서버로 전송된 데이터를 다른 서버, 혹은 호스팅을 사용중이라도 ftp기능을 지원한다면, 두 서버간에 데이터 공유가 가능합니다. 다시 말해 웹사이트는 A 호스트로 운영을 하고, 데이터(파일 서버)는 B 호스트에 보관하는데, 사용자 요청시만 A 호스트로 업로드하거나 다운로드합니다.

가능하다면 골드회원은 C 호스트 파일다운로드권한을 주고, 실버회원은 B 호스트 파일다운로드권한 부여를 해서 파일 관리도 가능할 지도 모릅니다.

다음은 사용자가 업로드한 파일을 B 호스트로 원격 업로드합니다.

예재(ex #1

 <?php 
 
// ftp는 상대경로, 절대경로가 허용되지 않으며,
 // 보통 public_html, www, html 로 시작합니다.
 // public_html/userid 에 자료를 저장한다면,
 // ftp 경로는 "public_html/userid/파일" 이 됩니다.

 // 디비에 저장될 파일 이름 
 
$filename $_FILES['userfile']['name'
];
 
// B 호스트에 저장될 실제 파일
 
$tmpfile md5("habony_" $_FILES['userfile']['tmp_name'
]); 
 
$fp fopen($tmpfile'r'
); 

 
// B 호스트 정보
 
$ftp_server "호스트 혹은 ip주소"

 
$ftp_user_name "접속 아이디"

 
$ftp_user_pass "접속 패스워드"


 
// B 호스트 접속
 
$conn_id ftp_connect($ftp_server
); 

 
// B 호스트 로그인 
 
$login_result ftp_login($conn_id$ftp_user_name$ftp_user_pass
); 

 
// 업로드 파일을 원격으로 B 호스트로 이동
 // B 호스트에 저장되면 DB 에 파일정보를 업데이트해줌
 // ftp_put 은 로컬에서만 가능하므로 ftp_fput을 사용합니다.
 
if (ftp_fput($conn_id$tmpfile$fpFTP_BINARY
)) { 
    echo 
"Successfully uploaded $filename\n"
;
 } else { 
    echo 
"There was a problem while uploading $file\n"

 } 

 
ftp_close($conn_id
); 
 
fclose($fp
); 
 
?>


필요시 업로드한 파일을 A 호스트로 가져 오는데, 이는 사용자가 파일 다운로드요청이나 이미지출력요청을 하였을 때만 처리되는 부분입니다.

예제(ex #2

 <?php 
 
// ftp는 상대경로, 절대경로가 허용되지 않으며,
 // 보통 public_html, www, html 로 시작합니다.
 // public_html/userid 에 자료를 저장한다면,
 // ftp 경로는 "public_html/userid/파일" 이 됩니다.

 // B 호스트에서 가져올 실제 파일
 
$remote_file "가져올 파일"
;
 
// A 호스트로 저장하거나 브라우저로 출력해야 할 파일
 
$local_file "저장할 파일"
;

 
// 임시 파일을 엽니다.
 
$fp fopen($local_file'w+'
);

  
// B 호스트 정보
 
$ftp_server "호스트 혹은 ip주소"

 
$ftp_user_name "접속 아이디"

 
$ftp_user_pass "접속 패스워드"


 
// B 호스트 접속
 
$conn_id ftp_connect($ftp_server
); 

 
// B 호스트 로그인 
 
$login_result ftp_login($conn_id$ftp_user_name$ftp_user_pass
);

 
// 파일을 A 호스트로 업로드하고, 
 // $file 로 다운로드하거나 저장할 코드를 작성하면 됩니다.
 // ftp_get 은 로컬에서만 가능하므로 ftp_fget을 사용합니다.
 
if (ftp_fget($conn_id$fp$remote_fileFTP_BINARY0
)) { 
    while(!
feof($fp
)){ 
         
$file .= fread($fp1024
); 
    }
    
// 파일 다운로드나 파일 출력 처리 부분입니다.
    
echo "Successfully written to $local_file\n"

 } else { 
    echo 
"There was a problem while downloading $remote_file 
            to $local_file\n"

 } 

 
ftp_close($conn_id
); 
 
fclose($fp
); 
 
?> 


사용자가 자료 삭제 요청하였을 때, B 호스트 파일 삭제 처리 부분입니다.

예제(ex #3

<?php
 
// ftp는 상대경로, 절대경로가 허용되지 않으며,
 // 보통 public_html, www, html 로 시작합니다.
 // public_html/userid 에 자료를 저장한다면,
 // ftp 경로는 "public_html/userid/파일" 이 됩니다.
 
$file 'public_html/test.php'
;

   
// B 호스트 정보
 
$ftp_server "호스트 혹은 ip주소"

 
$ftp_user_name "접속 아이디"

 
$ftp_user_pass "접속 패스워드"


 
// B 호스트 접속
 
$conn_id ftp_connect($ftp_server
); 

 
// B 호스트 로그인 
 
$login_result ftp_login($conn_id$ftp_user_name$ftp_user_pass
);

 
// B 호스트 파일 삭제
 // 파일 삭제가 정상적이면 DB 에 저장된 데이터도
 // 삭제 되도록 코드를 작성하면 됩니다.
 
if (ftp_delete($conn_id$file
)) {
      echo 
"$file deleted successful\n"
;
 } else {
      echo 
"could not delete $file\n"
;
 }

 
ftp_close($conn_id
);
 
?> 


이러한 기능은 서버일 경우 문제되지 않으나 호스팅을 받는 입장이라면 제한이 될 수 있습니다. 그래서 다음 코드로 ftp 지원여부 확인이 가능합니다.

 <?php
 
if(!function_exists('ftp_login'
)){
      echo 
"ftp 지원이 안됩니다."
;
 }
 
?>

 

블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

  • rootman 2019.04.05 21:36  댓글주소  수정/삭제  댓글쓰기

    글 읽고서 궁금한게 있어서 남깁니다.
    CI 프레임워크 사용중이고 php입니다.
    저 소스 적용하는 곳이 정확히 어느 곳인지 알 수 있을까요?

    • Favicon of https://blog.habonyphp.com BlogIcon 하보니 2019.04.08 11:42 신고  댓글주소  수정/삭제

      CodeIgniter 를 말씀하시는 것 같은데, 죄송하지만 CodeIgniter 는 잘 모릅니다.
      다만...
      일반적인 방법으로 설명드리자면...
      위 소스가 proc.php 로 저장되어 있다면...

      <form enctype="multipart/form-data" action="proc.php" method="post">
      <input type="file" name="userfile">
      <input type="submit" value="전송">
      </form>

      정도가 되지 않을까 싶습니다.

리플레이 공격방식은 프레젠테이션 공격이라 부르는데, 정상적인 사용자가 인증권한을 취득하기 위해 전송한 데이터를 재전송하는 모든 종류의 공격을 말합니다. 리플레이 공격과 마찬가지로 패스워드 스니핑 공격을 차단하려는 노력은 많지만 완전 차단방법은 없습니다.

그렇기 때문에 인증과정 중 폼의 여러 가지 속성을 설치한다 하여 공격자에게는 그다지 중요하지 않다 생각되는 잡다한 것으로 보며, 그래서인지 요즘은 HTTP요청내용과 HTTP응답내용이 노출되지 않게 보호하려는 방법으로 SSL전송방식을 많이 애용하는 편입니다. 허나 누가 뭐라해도 패스워드를 보호하는 일이야 말로 가장 중요한 부분임을 누구도 거부하지 않습니다.

이제는 _POST방식도 인증보호에 기대가 없고, 그렇다고 MD5도 믿음이 있어 보이지 않습니다. 왜냐하면 몇 년전에 이미 MD5가 복호화되어 암호가 뚤려 버렸기 때문입니다.

 <form action=https://mydomain.com/login.php method="POST"><br />
 myid:     <input type="text" name="username"><br />
 mypass:<input type="password" name="userpass"><br />
 </form> 

개인이 호스팅을 임대받는 경우라면 SSL기능을 자유롭게 사용할 수 없는 입장이므로 _GET전송방식보다는 인증노출이 적은 _POST방식을 많이 사용할 것을 권장하며, 비밀번호는 입력받아 MD5로 암호화하되 복잡한 암호를 사용하도록 사용자에게 유도하거나 개발자가 임의의 문자를 섞여 한번 더 암호화시켜 주어야 합니다.

다음으로 인증요청 무차별 공격 스크립트를 작성할 수 있습니다.

 <form action="http://mydomain.com/login.php" method="POST"><br />
 myid:     <input type="text" name="username"><br />
 mypass:<input type="password" name="userpass"><br />
 </form> 

 
<?php
 $host 
"mydomain.com"
;
 
$username "habony"
;
 
$userpass "1111"
;

 
$data "username=$username&userpass=$userpass"
;
 
$len strlen($data
);


 
// 헤더 구분은 \r\n로 해주어야 합니다.
 
$request ''
;
 
$request .= "POST /login.php HTTP/1.1\r\n"
;
 
$request .= "Host: ${host}\r\n"
;
 
$request .= "Content-Type: application/x-www-form-urlencoded\r\n"
;
 
$request .= "Content-Length: ${len}\r\n"
;
 
$request .= "Connection: close\r\n"
;

 
// 본문시작은 \r\n\r\n로 헤더와 바디로 구분합니다.
 
$request .= "\r\n"
;
 
$request .= "$data"
;

 
// HTTP요청은 기본 80포트입니다.
 
if($fp fsockopen($host80
)){
      
// mydomain.com 에 HTTP요청하고, HTTP응답을 받습니다.
      
fputs($fp$request
);

      
$response ''
;
      while(!
feof($fp
)){
            
// 1줄씩 응답을 읽어 옵니다.
           
$response .= fgets($fp1024
);
      }
      
fclose($fp
);
 }

 echo 
"$response<br />\n"
;

 
?>

이와 같은 작업으로 공격자는 인증시도를 하려할 것인데, $response의 결과에 따라 패스워드 취득 실패시 다른 패스워드 재시도 루틴을 요청할 수 있을 것입니다. 만약 사용자가 복잡한 암호를 구성하였다면, 공격자의 성공확률을 낮출 수 있습니다.

사용자 암호보호를 위해 암호화하는 것은 필요한 것이므로 무차별 공격을 어렵게 만들거나 성공확률을 낮추기 위해 30초정도 지연시킬 수 있습니다.

 <?php
 $uniqid 
uniqid(rand
());
 
// 아이디에 위험한 문자열이 있을 경우 ...
 
$inputid mysql_real_escape_string($_POST['inputid'
]);
 
// 사용자가 단순한 암호를 선택하였다면,
 // 개발자가 임의 문자를 붙여 한번 더 암호화시켜줍니다.
 // md5 함수는 16진수 32 문자로 반환합니다.
 // 16진수 32문자 = md5(문자열, [raw_output]);
 // raw_output는 PHP 5.0부터 사용 가능하며,
 // true로 설정하면 길이 16의 바이너리 형식으로 반환합니다.
 // md5는 문자열 암호화이고, md5_file는 파일 암호화로 동일하게 사용할 수 
있습니다.
 // echo md5("myid"); // 결과:cdce51bb5b16a770fbe0dd78e6d8a5bb
 // echo md5("myid", true); // 결과: 誥Q?&#52025;鎬?燕?
 
$inputpass md5($uniqid "_habony_" md5("habony_" 
$_POST['inputpass'], true
));

 

 
$data 
= array();
 
$sql 
= array();

 
$now time
();
 
$login_conn $now 30
;

 if(
$sql mysql_query("select logintime, inputpass from $db where 
inputid='${inputid}'"
)){
      if(
mysql_num_rows($sql
)){
           
$row mysql_fetch_assoc($sql
);
           if(
$row['logintime'] > $login_conn
){
                exit(
"로그인 실패하여 30초가 지나야 로그인 가능합니다."
);
           } elseif(
$row['inputpass'] === $inputpass
){
                echo 
"로그인 인증되었습니다."
;
           } else {
               
// 로그인 실패시 처리 부분...
                
mysql_query("update $db set logintime = '$now' where 
inputid = '$inputid' "
);
           }
      }  else {
           exit(
"해당하는 아이디가 없습니다."
);
      }
 }
 
?>


파일업로드된 파일접근을 막기 위해 이것 역시 암호화하여 저장할 필요가 있습니다.

 <?php
 $uniqid 
uniqid(rand
());
 
// 16진수 32문자 = md5_file(파일명, [raw_output]);
 // raw_output는 PHP 5.0부터 사용 가능하며,
 // true로 설정하면 길이 16의 바이너리 형식으로 반환합니다.
 // md5_file함수는 파일이 실제 존재해야 암호화됩니다.
 // 실패하면 php오류코드를 표시합니다.
 // md5_file은 다음과 같은 조건입니다.
 // if(file_exists($filename)){
 //      $md5filename = md5($uniqid . "_habony_". md5($filename, true));
 // }
 
$filename base64_encode($_FILES['userfile']['name'
]);
 
$md5filename md5($uniqid "_habony_"md5_file($filenametrue
));
 if(
$_FILES['userfile']['error'] === UPLOAD_ERR_OK
) {
      if(
$_FILES['userfile']['size'] <= 0
){
          echo 
"파일 업로드에 실패하였습니다."
;
      } else {
          
// HTTP post로 전송된 것인지 체크합니다.
          
if(!is_uploaded_file($_FILES['userfile']['tmp_name'
])) {
               echo 
"HTTP로 전송된 파일이 아닙니다."
;
          } else {
               
// move_uploaded_file은 임시 저장되어 있는 파일을 ./uploads 디렉토리로 이동합니다.
               
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $md5filename
)) {
                    echo 
"성공적으로 업로드 되었습니다.\n"
;
               } else {
                    echo 
"파일 업로드 실패입니다.\n"
;
               }
               
mysql_query(
"insert into $db values  ('','$filename');
          }
      }
 } else {
      echo file_errmsg($_FILES['userfile']['error']);
 }
 ?>


블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

  • MD5 2011.09.27 22:30  댓글주소  수정/삭제  댓글쓰기

    MD5가 뚫렸다는게 해시에서 원본을 찾아낼수 있게 뚫렸다는게 아닙니다.
    해시는 기본적으로 강한 충돌저항성을 가지는데 임의로 충돌을 만들어 내는데 성공했다고 합니다.
    이를 이용하면 예를들어 가짜 인증서를 만들수 있겠죠...

  • MD5 2011.09.27 22:31  댓글주소  수정/삭제  댓글쓰기

    일단 간단한 암호의 경우에는 브루트포스나 레이보우테이블을 이용해서 뚫는게 가능합니다.
    다만 충분히 강한 SOLT를 붙이면 훨씬 뚫기 힘들어지겠죠...

    • Favicon of https://blog.habonyphp.com BlogIcon 하보니 2011.09.28 18:17 신고  댓글주소  수정/삭제

      단순히 [a-z 0-9]로 이루어진 문자로는 보안이 약하다는 뜻이네요. 중간에 특수문자를 섞어두면 좀 안심이 되지 않을까요?

      조은 정보 감사합니다.

mixed pathinfo ( string $path [, int $options= PATHINFO_DIRNAME | PATHINFO_BASENAME | PATHINFO_EXTENSION | PATHINFO_FILENAME ] ) (PHP 4 >= 4.0.3, PHP 5)

이 함수는 두번째 인자를 생략할 경우 파일경로와 파일명, 확장자를 배열로 반환합니다. 파일이름([filename])은 [PHP 5.2.0] 부터 사용할 수 있습니다.

예제 (ex #1

 <?php
 $path_parts 
pathinfo('/www/htdocs/www//index.html'
);
 
print_r($path_parts
);
 
/*
 결과:
 Array
 (
    [dirname] => /www/htdocs/www
    [basename] => index.html
    [extension] => html
    [filename] => index
 )
 */


 
$path_parts pathinfo('/www/htdocs/www/index.php.asp.bmp.html.inc'
);
 
print_r($path_parts
);
 
/*
 결과:
 Array
 (
    [dirname] => /www/htdocs/www
    [basename] => index.php.asp.bmp.html.inc
    [extension] => inc
    [filename] => index.php.asp.bmp.html
 )
 */


 
$path_parts pathinfo('/www/htdocs/www/index'
);
 
print_r($path_parts
);
 
/*
 결과:
 Array
 (
    [dirname] => /www/htdocs/www
    [basename] => index
    [extension] => 
    [filename] => index
 )
 */
 
?>


다음은 두번째 인자를 이용한 파일 업로드시 활용 예제입니다.

예제 (ex #2
  <?php
 
if($_FILES['file']['error'] === UPLOAD_ERR_OK
) {
      
// 확장자를 반환받습니다.
      
if(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION) == "php"
) {
           echo 
"확장자 php파일은 업로드 하실수 없습니다."
;
      }
 }
 
?>

두번째 인자는 다음 표의 상수를 사용할 수 있습니다.

 PATHINFO_DIRNAME

 파일경로, [dirname] =>/www/htdocs/www

 PATHINFO_BASENAME  파일명, [basename] => index.html
 PATHINFO_EXTENSION  파일 확장자, [extension] => html
 PATHINFO_FILENAME   파일이름, [filename] => index

예제 (ex #3

 <?php
 
// 파일경로
 
$path_parts pathinfo('/www/htdocs/www///index.php.asp.bmp.html.inc',PATHINFO_DIRNAME
);
 echo 
$path_parts
// 결과: /www/htdocs/www
 // dirname함수도 같은 역할을 합니다.
 
echo dirname('/www/httpd/home/index.html'); 
// 결과: /www/httpd/home



 // 파일명
 
$path_parts pathinfo('/www/htdocs/www///index.php.asp.bmp.html.inc',PATHINFO_BASENAME
);
 echo 
$path_parts
// 결과: index.php.asp.bmp.html.inc
 // basename함수도 같은 역할을 합니다.
 
echo basename('/www/httpd/home/index.html'); 
// 결과: index.html
 // 두번째 인자를 사용할 수 있습니다.
 
echo basename('/www/httpd/home/index.html'".html"); 
// 결과: index




 // 파일 확장자
 
$path_parts pathinfo('/www/htdocs/www///index.php.asp.bmp.html.inc',PATHINFO_EXTENSION
);
 echo 
$path_parts
// 결과: inc




 // 파일이름
 
$path_parts pathinfo('/www/htdocs/www///index.php.asp.bmp.html.inc',PATHINFO_FILENAME
);
 echo 
$path_parts
// 결과: index.php.asp.bmp.html
 
?>


상대경로를 절대경로로 반환하는 realpath 함수

string realpath ( string $path ) (PHP 4, PHP 5)

예제 (ex #4
 <?php
 
echo realpath('./../../etc/passwd'); 
// 결과: /etc/passwd

 
echo realpath('/windows/system32'); 
// 결과: C:\WINDOWS\System32
 
?>
블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

php.ini에서 allow_url_fopen 을 On으로 활성화하면 HTTP나 FTP를 통해 파일을 작성하거나 읽어올 수 있습니다. HTTP인 경우 include, include_once, require, require_once를 사용할 수 있고, FTP는 fopen 으로 접속가능합니다.

FTP 접속은 "ftp://아이디:패스워드@도메인" 으로 접속가능하나 동일 파일이 이미 존재하면 fopen함수 호출에 실패한다는 점에 주의해야 합니다.

예제 (ex #1
  <?php
 
// (ex #1
 
if($file = @fopen (
   
"ftp://user_id:user_passwd@example.com/public_html/test.php""w"
)){
      
// 여기에서 데이터를 씁니다.
      
fwrite ($file"원격 파일 쓰기<br />\n"
);
      
fclose ($file
);
 } else {
    echo 
"<p>원격 파일을 쓰도록 열 수 없습니다.\n"
;
    exit;
 }
 
// 결과: 원격 파일 쓰기<br />\n


 // 이미 (ex #1 에서 test.php파일을 작성하였으므로 (ex #2 는 원격파일 작성에 실패합니다.
 // (ex #2
 
if($file = @fopen (
   
"ftp://user_id:user_passwd@example.com/public_html/test.php""w"
)){
      
// 여기에서 데이터를 씁니다.
      
fwrite ($file"원격 파일 쓰기<br />\n"
);
      
fclose ($file
);
 } else {
    echo 
"<p>원격 파일을 쓰도록 열 수 없습니다.\n"
;
    exit;
 }

 
/*
 결과:
 Warning: fopen(ftp://...@example.com/public_html/test.php
[function.fopen]: failed to open stream: Remote file already exists
 and overwrite context option not specified
 <br /> FTP server reports  213 49 in C:\Server\public_html\test.php 
on line 4
 */
 
?>

원격 접속시 동일 파일이 존재하면 덮어 쓰기는 되지 않지만 데이터 추가는 가능합니다.

예제 (ex #2
 <?php
  
if($file = @fopen (
   
ftp://user_id:user_passwd@example.com/public_html/test.php
    "a"
)){
      
// 여기에서 데이터를 씁니다.
      
fwrite ($file"원격 파일 쓰기<br />\n"
);
      
fclose ($file
);
 } else {
    echo 
"<p>원격 파일을 쓰도록 열 수 없습니다.\n"
;
    exit;
 }

 
// 결과: 원격 파일 쓰기<br />\n원격 파일 쓰기<br />\n

 
?>

원격 접속시 읽어 오기도 가능합니다.

예제 (ex #3

 <?php
  
if($file = @fopen (
   
ftp://user_id:user_passwd@example.com/public_html/test.php,
     
"r"
)){
      
// 여기에서 데이터를 읽어 옵니다.
      
while(!feof($fp
)){
           
$file .= fread($fp,1024
);
      }
      
fclose ($fp
);
 } else {
    echo 
"<p>원격 파일을 열 수 없습니다.\n"
;
    exit;
 }

 echo 
$file
;

 
// 결과: 원격 파일 쓰기<br />\n원격 파일 쓰기<br />\n

 
?>


간단하게 원격파일 접속에 대해 설명은 되었지만, allow_url_fopen 를 활성화하는 것을 권하지는 않습니다.
블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

복수의 파일은 input에서 다른 name을 사용하거나 배열로 조직화한 정보를 얻을 수 있습니다. 다중 파일 업로드 폼은 다음의 조건으로 구성할 수 있습니다.

 <form action="file-upload.php" method="post" enctype="multipart/form-data"><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input type="submit" value="파일 전송" />
 </form> 

폼전송시 file-upload.php파일에서는 다음 표로 구성하여 정보를 받을 수 있습니다.

 <?php
 
foreach($_FILES['userfile']['name'] as $key => $val
){
      if((
$_FILES['userfile']['size'][$key] > 0
){
           if(
$_FILES['userfile']['error'][$key] === UPLOAD_ERR_OK
){
                if(
is_uploaded_file($_FILES['userfile']['tmp_name'][$key
])){
                     
$filename md5("habony_".$_FILES['userfile']['name'][$key
]);
                     if(
move_uploaded_file($_FILES['userfile']['tmp_name'][$key],"./upload/".$filename
)){
                           
mysql_query(
"insert into $db value(
                           '',
                           '"
.addslashes($_FILES['userfile']['name'][$key]).
"'
                           )"
);
                     }
                }
           }
      }
 }
 
?> 

복수 파일 업로드를 허용하더라도 최대 파일 크기를 제한하려면 다음 예와 같을 것입니다.

 <form action="" method="post" enctype="multipart/form-data"><br />
   <input type="hidden" name="MAX_FILE_SIZE" value="300000" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input name="userfile[]" type="file" /><br />
   <input type="submit" value="파일 전송" />
 </form> 

 
<?php
 
if(is_array($_FILES['userfile']['name'
])){
     
$filesize 0
;
     foreach(
$_FILES['userfile']['size'] as $key => $val
){
          if(
$_FILES['userfile']['size'][$key] > 0
){
               
$filesize += $_FILES['userfile']['size'][$key
];
          }
     }
     
// 사용자 입력필드 파일 제한 크기
     
$maxfilesize = (int)$_POST['MAX_FILE_SIZE'
];
     if(
$filesize $maxfilesize
){
          echo 
"허용 파일용량을 초과하였습니다."
;
     } else {
       foreach(
$_FILES['userfile']['name'] as $key => $val
){
         if(
$_FILES['userfile']['size'][$key] > 0
){
               if(
$_FILES['userfile']['error'][$key] === UPLOAD_ERR_OK
){
               if(
is_uploaded_file($_FILES['userfile']['tmp_name'][$key
])){
                
$filename md5("habony_".$_FILES['userfile']['name'][$key
]);
                
$tmpfilename $_FILES['userfile']['tmp_name'][$key
];
                 if(
move_uploaded_file($tmpfilename,"./upload/".$filename
)){
                  
mysql_query(
"insert into $db value (
                                '',
                                '"
.addslashes($_FILES['userfile']['name'][$key]).
"'
                                       )"
);
                                  }
                        }
                   }
              }
          }
     }
 }
 
?>


블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

php는 POST로 파일 업로드기능을 제공합니다. RFC-1867 호환 브라우저(넷스케이프 네비게이터 3 이상, 마이크로소프트 인터넷 익스플로러 3+패치나 패치 없이 그 이상 버전을 포함)라면 파일 업로드를 받을 수 있는 기능을 제공합니다.

다음 표의 내용을 php.ini에서 조작할 수 있습니다.

 옵션  의미
 file_uploads

 업로드 기능을 사용할지를 결정합니다. 기본값 On

 upload_tmp_dir  업로드시 임시 저장 될 디렉토리 경로
 upload_max_filesize  허용하는 최대 파일 크기, 기본값 100M
 max_file_uploads  허용하는 최대 업로드 수, 기본값 100개

파일 업로드 폼은 다음 표처럼 작성하되 폼 안에 enctype="multipart/form-data"값이 있는지 확인하여야 합니다. 그렇지 않으면 업로드 기능은 작동하지 않습니다.

 <form enctype="multipart/form-data" action="send_ok.php" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    이 파일을 전송합니다: <input name="userfile" type="file" />
    <input type="submit" value="파일 전송" />
 </form>

method는 post로 정의하며, MAX_FILE_SIZE는 php.ini에 지정된 upload_max_filesize 크기 보다 클 수 는 없습니다. 이 필드는 ini에 지정된 파일크기보다 크면 에러를 표시하는 용도로만 사용되어야 합니다.

보통 하나의 파일을 업로드하면 다음 표의 변수($_FILES['파일명']['name'])를 여러개 가지게 됩니다.

 변수명  의미
 name  클라이언트측 원래 이름
 type  "image/gif"와 같은 파일의 mime형식, 그러나 php에서 확인하지 않으므로 이 값을 무시하여야 합니다.
 size  업로드된 파일의 바이트로 표현한 크기
 tmp_name
 서버에 저장된 업로드된 파일의 임시 파일 이름
 error  파일 업로드에 대한 에러 코드를 표시

파일 업로드는 다음 예제와 같은 과정으로 작성하면 됩니다.

예제 (ex #1

  <form enctype="multipart/form-data" action="" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    이 파일을 전송합니다: <input name="userfile" type="file" />
    <input type="submit" value="파일 전송" />
 </form>

 
<?php
 
// uploads디렉토리에 파일을 업로드합니다.
 
$uploaddir './uploads/'
;
 
$uploadfile $uploaddir basename($_FILES['userfile']['name'
]);

 echo 
'<pre>'
;
 if(
$_POST['MAX_FILE_SIZE'] < $_FILES['userfile']['size'
]){
      echo 
"업로드 파일이 지정된 파일크기보다 큽니다.\n"
;
 } else {
     if((
$_FILES['userfile']['error'] > 0) || ($_FILES['userfile']['size'] <= 0
)){
          echo 
"파일 업로드에 실패하였습니다."
;
     } else {
          
// HTTP post로 전송된 것인지 체크합니다.
          
if(!is_uploaded_file($_FILES['userfile']['tmp_name'
])) {
                echo 
"HTTP로 전송된 파일이 아닙니다."
;
          } else {
                
// move_uploaded_file은 임시 저장되어 있는 파일을 ./uploads 디렉토리로 이동합니다.
                
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile
)) {
                     echo 
"성공적으로 업로드 되었습니다.\n"
;
                } else {
                     echo 
"파일 업로드 실패입니다.\n"
;
                }
          }
     }
 }

 
print_r($_FILES
);

 
/*
 결과:
 성공적으로 업로드 되었습니다.
 Array
 (
    [userfile] => Array
        (
            [name] => config.sys
            [type] => text/plain
            [tmp_name] => /tmp/phpXTtzBW
            [error] => 0
            [size] => 10
        )
 )
 */
 
?> 


파일 업로드가 성공적이면 에러코드는 0을 가집니다. 에러 코드는 다음 표의 상수로 대조해도 됩니다.

 상수명  의미
 UPLOAD_ERR_OK  값: 0; 오류 없이 파일 업로드가 성공했습니다
 UPLOAD_ERR_INI_SIZE 값: 1; 업로드한 파일이 php.ini upload_max_filesize 지시어보다 큽니다
 UPLOAD_ERR_FORM_SIZE 
값: 2; 업로드한 파일이 HTML 폼에서 지정한 MAX_FILE_SIZE 보다 큽니다. 
 UPLOAD_ERR_PARTIAL 
값: 3; 파일이 일부분만 전송되었습니다
 UPLOAD_ERR_NO_FILE  값: 4; 파일이 전송되지 않았습니다
 UPLOAD_ERR_NO_TMP_DIR  값: 6; 임시 폴더가 없습니다. PHP 4.3.10과 PHP 5.0.3에서 추가.
 UPLOAD_ERR_CANT_WRITE  값: 7; 디스크에 파일 쓰기를 실패했습니다. PHP 5.1.0에서 추가
 UPLOAD_ERR_EXTENSION  값: 8; 확장에 의해 파일 업로드가 중지되었습니다. PHP 5.2.0에서 추가.

파일 이름을 서버에 그대로 저장하는 것도 보안상 상당한 위험이 있으므로 md5로 암호화해서 저장하고, 디비에 원래 이름을 저장하도록 합니다.

예제 (ex #2

   <form enctype="multipart/form-data" action="" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    이 파일을 전송합니다: <input name="userfile" type="file" />
    <input type="submit" value="파일 전송" />
 </form>

 
<?php
 
function file_errmsg($code
){
     switch(
$code
){
         case(
UPLOAD_ERR_INI_SIZE
):
         return 
"업로드한 파일이 php.ini upload_max_filesize보다 큽니다."
;
     case(
UPLOAD_ERR_FORM_SIZE
):
         return 
"업로드한 파일이 MAX_FILE_SIZE 보다 큽니다. "
;
     case(
UPLOAD_ERR_PARTIAL
):
         return 
"파일이 일부분만 전송되었습니다. 다시 시도해 주십시요."
;
     case(
UPLOAD_ERR_NO_FILE
):
         return 
"파일이 전송되지 않았습니다."
;
     case(
UPLOAD_ERR_NO_TMP_DIR
):
         return 
"임시 폴더가 없습니다."
;
     case(
UPLOAD_ERR_CANT_WRITE
):
         return 
"디스크에 파일 쓰기를 실패했습니다. 다시 시도해 주십시요."
;
     default:
         return 
"확장에 의해 파일 업로드가 중지되었습니다."
;
     }
 }

 
// 서버에 저장될 디렉토리이름
 
$uploaddir './uploads/'
;
 
// 서버에 저장될 파일이름
 
$filename basename($_FILES['userfile']['name'
]);
 
$md5filename $uploaddir md5("habony_".$filename
);
 
$ext array_pop(explode(".","$filename"
);

 echo 
'<pre>'
;
 if(
$_FILES['userfile']['error'] === UPLOAD_ERR_OK
) {
      if(
strtolower($ext) == "php"
) {
           echo 
"확장자 php파일은 업로드 하실수 없습니다."
;
      }
      else if(
$_FILES['userfile']['size'] <= 0
){
          echo 
"파일 업로드에 실패하였습니다."
;
      } else {
          
// HTTP post로 전송된 것인지 체크합니다.
          
if(!is_uploaded_file($_FILES['userfile']['tmp_name'
])) {
               echo 
"HTTP로 전송된 파일이 아닙니다."
;
          } else {
               
// move_uploaded_file은 임시 저장되어 있는 파일을 ./uploads 디렉토리로 이동합니다.
               
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $md5filename
)) {
                    echo 
"성공적으로 업로드 되었습니다.\n"
;
               } else {
                    echo 
"파일 업로드 실패입니다.\n"
;
               }
               
mysql_query("insert into $db values  ('','$filename')"
);
          }
      }
 } else {
      echo 
file_errmsg($_FILES['userfile']['error'
]);
 }

 
print_r($_FILES
);

 
/*
 결과:
 성공적으로 업로드 되었습니다.
 Array
 (
    [userfile] => Array
        (
            [name] => config.sys
            [type] => text/plain
            [tmp_name] => /tmp/phpXTtzBW
            [error] => 0
            [size] => 10
        )
 )
 */
 
?>

블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요

resource fopen ( string $filename , string $mode [, bool $use_include_path= false [, resource $context ]] ) (PHP 4, PHP 5)

이 함수는 호스트의 파일을 열거나 새로 만듭니다.
첫 번째 인자는 파일명 또는 절대경로를 입력하고, 두 번째 인자는 다음 표의 모드를 사용할 수 있습니다.

  모 드       의 미
 r 읽기 전용으로 오픈합니다.
 r+ 읽기와 쓰기 모드로 오픈합니다.
 w 쓰기 전용으로 오픈합니다. 기존 파일 내용은 완전히 지워지고, 새로 만듭니다. 파일이  존재하지 않는다면 새로 만듭니다.
 w+ 읽기와 쓰기 모드로 오픈합니다. 기존 파일 내용은 완전히 지워지고, 새로 만듭니다. 파일이  존재하지 않는다면 새로 만듭니다.
 a 내용 추가, 파일의 끝에 내용을 추가합니다. 파일이 존재하지 않는다면 새로 만듭니다.
 a+ 내용 추가와 읽기모드로 오픈하여 파일의 끝에 내용을 추가합니다. 파일이  존재하지 않는다면 새로 만듭니다.
 b 바이너리모드로 오픈합니다. 윈도우환경에서는 필수 모드

다음은 바이너리 그림 출력예제입니다.

예제 (ex #1
 <?php
 
// rb -> 읽기전용, 바이너리로 오픈합니다.
 
if($fp fopen('logo.gif''rb'
)){
     
// 바이너리로 읽기
     // 파일 포인터로 지정된 파일에서 최대 길이 1024*100 만큼 브라우저로 출력합니다.
      
print(fread($fp,1024*100
));
      
flush
();
      
// 파일을 오픈하면, 다른 스크립트에서  이용할 수 있도록 반드시 파일 포인터를 닫아야 합니다.
      
fclose($fp
);
 } else {
     print(
'파일을 찾을 수 없습니다.'
);
 }
 
?>

예제 (ex #2

 <?php
 $filename 
'test.bmp'
;

 
header("content-type: file/unknown"
);
 
header("content-length: ".filesize($filename
));
 
header("content-disposition: attachment; filename=\"${filename}\""
);
 
header("content-description: php generated data"
);
 
header("pragma: no-cache"
);
 
header("expires: 0"
);

 if(
$fp fopen($filename'rb'
)){
     while(!
feof($fp
)) {
          print(
fread($fp,1024
));
          
flush
();
     }
     
fclose($fp
);
 } else {
     print(
'파일을 찾을 수 없습니다.'
);
 }
 
?>


fpassthru함수는 처음 파일 포인터에서 끝까지의 파일 내용을 읽어 표준 출력으로 보냅니다.

예제 (ex #3
 <?php
 
// 읽기전용으로 오픈합니다.
 
if($fp fopen('readme.txt''rb'
)){
       
fpassthru($fp
);
       
flush
();
       
fclose($fp
);
 } else {
     print(
'파일을 찾을 수 없습니다.'
);
 }
 
?>


관련글: 2013/06/07 - [phP 함수 레퍼런스/파일 시스템 함수] - fopen 함수의 b flag 문제


블로그 이미지

하보니

하보니와 함께하는 phP 초보

댓글을 달아 주세요