PHP의`post_max_size`를 초과하는 파일을 정상적으로 처리하는 방법은 무엇입니까?


86

이메일에 파일을 첨부하는 PHP 양식을 작업 중이며 업로드 된 파일이 너무 큰 경우를 정상적으로 처리하려고합니다.

나는 두 설정이 있다는 것을 배웠다 php.ini즉 파일 업로드의 maxiumum 크기에 영향을 upload_max_filesize하고 post_max_size.

파일 크기가를 초과 upload_max_filesize하면 PHP는 파일 크기를 0으로 반환합니다. 괜찮습니다. 확인할 수 있습니다.

그러나을 초과하면 post_max_size스크립트가 자동으로 실패하고 빈 양식으로 돌아갑니다.

이 오류를 잡을 방법이 있습니까?


1
php.ini에 대한 액세스 권한이 있습니까? post_max_size는 upload_max_filesize보다 크게 설정해야합니다. 또한 ca2.php.net/manual/en/features.file-upload.post-method.php에
Matt McCormick

@Matt McCormick-MAX_FILE_SIZE 입력이 훌륭하게 작동합니다. 파일 크기가이 값을 초과하면 파일 크기가 이제 0으로 표시됩니다. 이는 이미 처리 한 사례입니다. 악의적 인 사용자가이를 우회 할 수는 있지만 일반 사용자를 위해 정상적으로 실패하려고하기 때문에 여기서는 내 목적에 부합합니다.
Nathan Long

답변:


55

에서 문서 :

게시 데이터의 크기가 post_max_size보다 크면 $ _POST 및 $ _FILES 수퍼 글로벌이 비어 있습니다. 이는 다양한 방법으로 추적 할 수 있습니다. 예를 들어 데이터를 처리하는 스크립트에 $ _GET 변수를 전달 (예 : <form action = "edit.php? processed = 1">)하고 $ _GET [ 'processed']가 세트.

따라서 불행히도 PHP가 오류를 보내는 것처럼 보이지 않습니다. 그리고 비어있는 $ _POST 배열을 보내기 때문에 스크립트가 빈 양식으로 돌아가는 이유입니다. POST라고 생각하지 않습니다. (아주 좋지 않은 디자인 결정 IMHO)

이 댓글 작성자 도 흥미로운 아이디어를 가지고 있습니다.

보다 우아한 방법은 post_max_size와 $ _SERVER [ 'CONTENT_LENGTH']를 비교하는 것 같습니다. 후자는 업로드 된 파일의 크기와 포스트 데이터뿐만 아니라 멀티 파트 시퀀스도 포함합니다.


3
굵은 부분을 읽어주세요. 즉, 파일 크기가 upload_max_filesize를 초과하면 사용자가 양식이 post_max_size를 초과하면 어떻게되는지 묻습니다. 이 문제를 방지하려면 post_max_size를 upload_max_filesize보다 높게 설정해야하지만 OP에는 동일하게 유지해야하는 이유가있을 수 있습니다.
Matt McCormick

1
죄송합니다. post_max_size와 upload_max_filesize를 섞었습니다. +1
페카

@Matt-post_max_size IS가 upload_max_filesize보다 높게 설정되었지만 업로드가 둘 다 초과하면 여전히 실패합니다. 둘 사이에 있으면 파일 크기가 0으로 표시됩니다.
Nathan Long

1
당신은 그것을 해결했지만 네 post_max_size를 사용할 수 있습니다. ini_get ( 'post_max_size')를 수행하십시오. ini_get ()을 사용하여 다른 INI 설정을 확인할 수도 있습니다.
Matt McCormick

1
@SavasVedova-지적 해 주셔서 감사하지만 더 이상 문제를 해결할 수 없습니다. 몇 년이 지났고 더 이상 그 회사 나 PHP에서 일하지 않습니다. :)
Nathan Long

45

최대 게시물 크기를 초과하는 파일을 포착 / 처리하는 방법이 있습니다. 이것은 최종 사용자에게 무슨 일이 있었는지, 누가 잘못했는지 알려주기 때문에 제가 선호하는 것입니다.)

if (empty($_FILES) && empty($_POST) &&
        isset($_SERVER['REQUEST_METHOD']) &&
        strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
    //catch file overload error...
    $postMax = ini_get('post_max_size'); //grab the size limits...
    echo "<p style=\"color: #F00;\">\nPlease note files larger than {$postMax} will result in this error!<br>Please be advised this is not a limitation in the CMS, This is a limitation of the hosting server.<br>For various reasons they limit the max size of uploaded files, if you have access to the php ini file you can fix this by changing the post_max_size setting.<br> If you can't then please ask your host to increase the size limits, or use the FTP uploaded form</p>"; // echo out error and solutions...
    addForm(); //bounce back to the just filled out form.
}
else {
    // continue on with processing of the page...
}

2
이것은 php.ini에서 track_errors = Off, 아마도 display_errors = Off 및 display_startup_errors = Off 일 때 작동합니다. 그렇지 않으면 PHP는 그렇게 멀리 가지 않고 질문 제목과 같이 경고를 보냅니다. 그러나 프로덕션 시스템에서는 php.ini 설정이어야하므로 잘 작동합니다.
raoulsson

2
이 깔끔한 아이디어는 내 테스트 (PHP / 5.5.8)에서 잘 작동합니다. 또한 복용을 향상시킬 수 $_SERVER['CONTENT_LENGTH']upload_max_filesize계정에 있습니다.
Álvaro González 2014 년

에서의 선도 raoulsson 주석의 오류를 억제 당신이 환경에서하지 않으면 경고를 억제 할 수있는 방법은 무엇입니까?
brendo

6

$ _POST 및 $ _FILES의 비어 있는지 확인이 작동하지 않는 SOAP 요청에 대한 문제가 있습니다. 유효한 요청에서도 비어 있기 때문입니다.

따라서 CONTENT_LENGTH와 post_max_size를 비교하는 검사를 구현했습니다. 던져진 예외는 나중에 등록 된 예외 핸들러에 의해 XML-SOAP-FAULT로 변환됩니다.

private function checkPostSizeExceeded() {
    $maxPostSize = $this->iniGetBytes('post_max_size');

    if ($_SERVER['CONTENT_LENGTH'] > $maxPostSize) {
        throw new Exception(
            sprintf('Max post size exceeded! Got %s bytes, but limit is %s bytes.',
                $_SERVER['CONTENT_LENGTH'],
                $maxPostSize
            )
        );
    }
}

private function iniGetBytes($val)
{
    $val = trim(ini_get($val));
    if ($val != '') {
        $last = strtolower(
            $val{strlen($val) - 1}
        );
    } else {
        $last = '';
    }
    switch ($last) {
        // The 'G' modifier is available since PHP 5.1.0
        case 'g':
            $val *= 1024;
            // fall through
        case 'm':
            $val *= 1024;
            // fall through
        case 'k':
            $val *= 1024;
            // fall through
    }

    return $val;
}

@ manuel-azar : 추가 된 "휴식"단계가 올바르지 않습니다. 그들은
staabm

크기 초과 여부를 확인할 필요가 없습니다. 파일이 없으면 content_length가 없습니다. 따라서 content_length가 설정되어 있고 게시물 및 파일 변수가 비어 있는지 확인하기 만하면됩니다. 아니?
ADJenks

4

@Matt McCormick 및 @AbdullahAJM의 답변을 바탕으로 테스트에 사용 된 변수가 설정되었는지 확인한 다음 $ _SERVER [ 'CONTENT_LENGTH']가 php_max_filesize 설정을 초과하는지 확인하는 PHP 테스트 케이스가 있습니다.

            if (
                isset( $_SERVER['REQUEST_METHOD'] )      &&
                ($_SERVER['REQUEST_METHOD'] === 'POST' ) &&
                isset( $_SERVER['CONTENT_LENGTH'] )      &&
                ( empty( $_POST ) )
            ) {
                $max_post_size = ini_get('post_max_size');
                $content_length = $_SERVER['CONTENT_LENGTH'] / 1024 / 1024;
                if ($content_length > $max_post_size ) {
                    print "<div class='updated fade'>" .
                        sprintf(
                            __('It appears you tried to upload %d MiB of data but the PHP post_max_size is %d MiB.', 'csa-slplus'),
                            $content_length,
                            $max_post_size
                        ) .
                        '<br/>' .
                        __( 'Try increasing the post_max_size setting in your php.ini file.' , 'csa-slplus' ) .
                        '</div>';
                }
            }

이것이 가장 논리적 인 방법입니다. _post가 비어 있지만 콘텐츠 길이가 아닌지 확인하십시오. 크기를 비교할 필요가 없습니다.
ADJenks

1

이 문제를 해결하는 간단한 방법입니다.

코드 시작시 "checkPostSizeExceeded"를 호출하면됩니다.

function checkPostSizeExceeded() {
        if (isset($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'POST' and
            isset($_SERVER['CONTENT_LENGTH']) and empty($_POST)//if is a post request and $_POST variable is empty(a symptom of "post max size error")
        ) {
            $max = get_ini_bytes('post_max_size');//get the limit of post size 
            $send = $_SERVER['CONTENT_LENGTH'];//get the sent post size

            if($max < $_SERVER['CONTENT_LENGTH'])//compare
                throw new Exception(
                    'Max size exceeded! Were sent ' . 
                        number_format($send/(1024*1024), 2) . 'MB, but ' . number_format($max/(1024*1024), 2) . 'MB is the application limit.'
                    );
        }
    }

이 보조 기능을 복사하십시오.

function get_ini_bytes($attr){
    $attr_value = trim(ini_get($attr));

    if ($attr_value != '') {
        $type_byte = strtolower(
            $attr_value{strlen($attr_value) - 1}
        );
    } else
        return $attr_value;

    switch ($type_byte) {
        case 'g': $attr_value *= 1024*1024*1024; break;
        case 'm': $attr_value *= 1024*1024; break;
        case 'k': $attr_value *= 1024; break;
    }

    return $attr_value;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.