PHP के `post_max_size` को पार करने वाली फ़ाइलों को कैसे इनायत करें?


86

मैं एक PHP फॉर्म पर काम कर रहा हूं जो एक ईमेल पर एक फाइल संलग्न करता है, और उन मामलों को इनायत करने की कोशिश करता है जहां अपलोड की गई फ़ाइल बहुत बड़ी है।

मैंने सीखा है कि दो सेटिंग्स हैं php.iniजो फ़ाइल अपलोड के अधिकतम आकार को प्रभावित करती हैं: upload_max_filesizeऔर post_max_size

यदि फ़ाइल का आकार अधिक है upload_max_filesize, तो PHP फ़ाइल का आकार 0. लौटाता है; यह ठीक है; मैं उसके लिए जाँच कर सकता हूँ।

लेकिन अगर यह अधिक हो जाता है post_max_size, तो मेरी स्क्रिप्ट चुपचाप विफल हो जाती है और खाली रूप में वापस चली जाती है।

क्या इस त्रुटि को पकड़ने का कोई तरीका है?


1
क्या आपके पास php.ini तक पहुंच है? post_max_size को upload_max_filesize से बड़ा सेट किया जाना चाहिए। आपको फ़ॉर्म पर <ca
मैट मैककॉर्मिक

@Matt मैककॉर्मिक - MAX_FILE_SIZE इनपुट शानदार काम करता है - यदि फ़ाइल का आकार इससे अधिक है, तो फ़ाइल का आकार अब 0 के रूप में दिखाता है, जो एक ऐसा मामला है जिसे मैंने पहले ही संभाल लिया है। भले ही यह एक दुर्भावनापूर्ण उपयोगकर्ता द्वारा बायपास किया जा सकता है, यह यहाँ मेरे उद्देश्यों को पूरा करता है, क्योंकि मैं सिर्फ नियमित उपयोगकर्ताओं के लिए कृपापूर्वक विफल होने की कोशिश कर रहा हूं।
नाथन लॉन्ग

जवाबों:


55

से प्रलेखन :

यदि पोस्ट डेटा का आकार post_max_size से अधिक है, तो $ _POST और $ _FILES सुपरग्लोब खाली हैं । इसे विभिन्न तरीकों से ट्रैक किया जा सकता है, उदाहरण के लिए डेटा प्रोसेसिंग करने वाली स्क्रिप्ट में $ _GET वैरिएबल पास करके, अर्थात <form action = "edit.php? संसाधित = 1">, और फिर जाँच करें कि क्या $ _GET ['संसाधित'] सेट।

तो दुर्भाग्य से, ऐसा नहीं लगता है कि PHP एक त्रुटि भेजता है। और जब से यह खाली $ _POST सरणी भेजता है, यही कारण है कि आपकी स्क्रिप्ट रिक्त रूप में वापस जा रही है - यह नहीं लगता कि यह एक POST है। (काफी खराब डिजाइन निर्णय IMHO)

इस टिप्पणीकार का एक दिलचस्प विचार भी है।

ऐसा लगता है कि post_max_size और $ _SERVER ['CONTENT_LENGTH'] के बीच एक अधिक सुरुचिपूर्ण तरीका तुलनात्मक है। कृपया ध्यान दें कि उत्तरार्द्ध में न केवल अपलोड की गई फ़ाइल के आकार के साथ-साथ पोस्ट डेटा भी शामिल है, लेकिन अनुक्रमों को भी गुणा करें।


3
कृपया बोल्ड भाग पढ़ें। यदि फ़ाइल का आकार upload_max_filesize से अधिक है, तो उपयोगकर्ता पूछ रहा है कि जब फॉर्म post_max_size से अधिक हो जाता है तो क्या होता है। post_max_size को इस समस्या से बचने के लिए upload_max_filesize से अधिक सेट किया जाना चाहिए, लेकिन ओपी के पास इसे रखने के लिए कारण हो सकते हैं।
मैट मैककॉर्मिक

1
क्षमा करें, मैंने post_max_size और upload_max_filesize मिलाया है। +1
पीका

@Matt - post_max_size IS को upload_max_filesize से अधिक सेट किया गया है, लेकिन मुझे अभी भी विफलता मिलती है यदि अपलोड दोनों से अधिक हो। अगर यह दोनों के बीच में पड़ता है, तो मैं देखता हूं कि फ़ाइल का आकार 0.
नाथन लॉन्ग

1
आपने इसे हल कर लिया है, लेकिन हां post_max_size उपलब्ध है। बस ini_get ('post_max_size') करें। ini_get () का उपयोग अन्य INI सेटिंग्स को जांचने के लिए भी किया जा सकता है।
मैट मैककॉर्मिक

1
@SavasVedova - इस ओर इशारा करने के लिए धन्यवाद, लेकिन मैं अब समस्या निवारण नहीं कर सकता। कुछ साल हो गए हैं और मैं अब उस कंपनी या PHP में काम नहीं करता। :)
नाथन लॉन्ग

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
यह तब काम करता है जब Track_errors = Off, संभवतः php.ini में display_errors = Off और display_startup_errors = Off भी प्रदर्शित होता है। अन्यथा PHP को वह दूर भी नहीं मिलेगा और चेतावनी भेजेगा, जैसे प्रश्न शीर्षक में। लेकिन एक उत्पादन प्रणाली में यह php.ini सेटिंग होना चाहिए, इसलिए यह बहुत अच्छा काम करता है।
रौल्सन डेस 15'13

2
यह साफ विचार मेरे परीक्षणों (PHP / 5.5.8) में ठीक काम कर रहा है। इसे खाते में $_SERVER['CONTENT_LENGTH']और लेते हुए बढ़ाया जा सकता है upload_max_filesize
अल्वारो गोंजालेज

Raoulsson की टिप्पणी से आगे बढ़ने पर , क्या चेतावनी को दबाने का कोई तरीका है यदि आप उस वातावरण में नहीं हैं जिसमें त्रुटियों को दबा दिया गया है?
ब्रेंडो

6

हमें SOAP अनुरोधों के लिए समस्या हुई जहां $ _POST और $ _FILES की शून्यता के लिए एक चेक काम नहीं करता है, क्योंकि वे वैध अनुरोधों पर भी खाली हैं।

इसलिए हमने 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;
}

@ मैनुअल-अजार: जोड़ा गया "ब्रेक" स्टेप सही नहीं है। वे वहाँ नहीं हैं .. 3v4l.org/ABfGs
staabm

यदि आकार से अधिक है तो चेक को देखना अनावश्यक है। यदि कोई फ़ाइल नहीं थी, तो कोई content_length नहीं होगी। तो आपको बस यह देखना है कि क्या content_length सेट है और पोस्ट और फ़ाइल चर खाली हैं या नहीं। नहीं?
ADJenks

4

@Matt McCormick's और @ AbdullahAJM के उत्तरों के आधार पर, यहां एक PHP परीक्षण मामला है जो परीक्षण में उपयोग किए जाने वाले चर की जांच करता है और फिर जाँचता है कि क्या $ _SERVER ['CONTENT_LENGTH' php_max_filesize सेटिंग से अधिक है:

            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;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.