上传前检查文件大小

38

我正在使用从这里获取的javascript代码,它完美地实现了我的需求。

var _validFileExtensions = [".jpg", ".jpeg"]; 

function File_Validator(theForm){
    var arrInputs = theForm.getElementsByTagName("input"); 
    for (var i = 0; i < arrInputs.length; i++) { 
    var oInput = arrInputs[i]; 
    if (oInput.type == "file") { 
        var sFileName = oInput.value; 
        var blnValid = false; 
            for (var j = 0; j < _validFileExtensions.length; j++) { 
                var sCurExtension = _validFileExtensions[j]; 
                if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) { 
                    blnValid = true; 
                    break; 
                    } 
                } 

                if (!blnValid) { 
                    alert("Invalid image file type!"); 
                    return false; 
                } 
        } 
    } 

return true; 
} 

现在,我想知道是否可以在提交/上传按钮之前检查文件大小,并在文件大于500kb时失败?

编辑

在研究了PHPMyCoder建议的内容之后,我最终通过使用这段JavaScript代码来解决问题:

<script language='JavaScript'>
function checkFileSize(inputFile) {
var max =  3 * 512 * 512; // 786MB

if (inputFile.files && inputFile.files[0].size > max) {
    alert("File too large."); // Do your thing to handle the error.
    inputFile.value = null; // Clear the field.
   }
}
</script>

这段代码检查文件大小,在提交表单之前警告用户。


2
你应该意识到文件扩展名实际上几乎毫无意义,对吧?任何人都可以将任何扩展名更改为他们想要的任何东西。 - Pointy
我已经有一个提交后失败的包含,但我想在提交之前向用户提醒。不确定如何使用HTML5文件API。 - cchap
@cchap 在我的回答中演示了HTML5文件API的演示(以及工作演示链接)。 - Bailey Parker
@Pointy 简单的安全功能... 根据扩展名检查内容类型.... - james walker
3个回答

61

客户端上传取消

在现代浏览器上(FF >= 3.6,Chrome >= 19.0,Opera >= 12.0,以及有缺陷的 Safari),可以使用HTML5 文件 API。当文件输入框中的值发生变化时,该 API 将允许您检查文件大小是否符合要求。当然,这个和 MAX_FILE_SIZE 都可能被篡改,因此始终要使用服务器端验证。

<form method="post" enctype="multipart/form-data" action="upload.php">
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" value="Submit" />
</form>

<script>
document.forms[0].addEventListener('submit', function( evt ) {
    var file = document.getElementById('file').files[0];

    if(file && file.size < 10485760) { // 10 MB (this size is in bytes)
        //Submit form        
    } else {
        //Prevent default and display error
        evt.preventDefault();
    }
}, false);
</script>

服务器端上传取消

在服务器端,由于一旦调用了PHP,上传就已经完成,因此无法通过PHP停止上传。如果您想节省带宽,可以使用ini设置upload_max_filesize来拒绝服务器端的上传。但是,这样做会对所有上传都生效,因此您必须选择适合所有上传的宽松设置。其他答案中已经讨论了MAX_FILE_SIZE的使用。我建议阅读相关手册。请注意,与客户端相关的任何内容(包括javascript检查)都可能被篡改,因此您始终应该进行服务器端(PHP)验证。

PHP验证

在服务器端,您应该验证文件是否符合大小限制(因为在INI设置之外,前面的所有内容都可能被篡改)。您可以使用$_FILES数组来查找上传文件的大小。(有关$_FILES的详细内容,请参见MAX_FILE_SIZE文档下方的文档)

upload.php

<?php
if(isset($_FILES['file'])) {
    if($_FILES['file']['size'] > 10485760) { //10 MB (size is also in bytes)
        // File too big
    } else {
        // File within size restrictions
    }
}

编辑php.ini的upload_max_filesize并没有像你提到的那样完全奏效,不幸的是它适用于所有文件上传。我尝试了html5文件API,但它仍然会执行提交操作。 - cchap
如果($_FILES['file']['size'] > 10485760) { 我已经在使用它了,它可以正常工作,如果文件大于500kb,则不会上传,但我想在提交表单之前发出警报。 - cchap
@cchap 你有看到我回答中“客户端取消”一节下的文本吗?那段文字可以让你在用户提交表单之前警告用户。 - Bailey Parker
这个 $_FILES['file']['size'] 检查安全吗?黑客不是可以更改头信息(包括 ['size'])吗? - doubleOrt

12

我创建了一个 jQuery 版本的 PhpMyCoder 的答案:

$('form').submit(function( e ) {    
    if(!($('#file')[0].files[0].size < 10485760 && get_extension($('#file').val()) == 'jpg')) { // 10 MB (this size is in bytes)
        //Prevent default and display error
        alert("File is wrong type or over 10Mb in size!");
        e.preventDefault();
    }
});

function get_extension(filename) {
    return filename.split('.').pop().toLowerCase();
}

get_extension 函数也可以这样写:return filename.split('.').pop().toLowerCase(); - kano

-5

在浏览器中运行的JavaScript通常无法访问本地文件系统,因为它超出了沙箱的范围。所以我认为答案是不可以。


这并不完全正确:HTML5 API添加了使用JavaScript读取特定文件的可能性,只要用户在输入中选择了它。 - Sebastien C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接