【问题标题】:Limit the size of a file upload (html input element)限制文件上传的大小(html输入元素)
【发布时间】:2011-04-18 01:09:29
【问题描述】:

我想简单地限制用户可以上传的文件的大小。

我认为 maxlength = 20000 = 20k 但这似乎根本不起作用。

我在 Rails 上运行,而不是 PHP,但我认为在 HTML/CSS 客户端执行它会更简单,或者作为最后的手段使用 jQuery。这是非常基本的,但肯定有一些我遗漏或不知道的 HTML 标记。

希望支持 IE7+、Chrome、FF3.6+。如果有必要,我想我可以只支持 IE8+。

谢谢。

【问题讨论】:

  • 有可能。请参考this问题。

标签: html


【解决方案1】:

这是完全可能的。使用 Javascript。

我使用 jQuery 来选择输入元素。我设置了一个 on change 事件。

$("#aFile_upload").on("change", function (e) {

    var count=1;
    var files = e.currentTarget.files; // puts all files into an array

    // call them as such; files[0].size will get you the file size of the 0th file
    for (var x in files) {

        var filesize = ((files[x].size/1024)/1024).toFixed(4); // MB

        if (files[x].name != "item" && typeof files[x].name != "undefined" && filesize <= 10) { 

            if (count > 1) {

                approvedHTML += ", "+files[x].name;
            }
            else {

                approvedHTML += files[x].name;
            }

            count++;
        }
    }
    $("#approvedFiles").val(approvedHTML);

});

在提交实际发生之前,上面的代码将我认为值得保留的所有文件名保存到提交页面。我使用 jQuery 将“已批准”文件添加到输入元素的 val 中,因此表单提交将发送我要保存的文件的名称。所有文件都将被提交,但是,现在在服务器端我们必须过滤掉这些文件。我还没有为此编写任何代码,但请发挥你的想象力。我假设可以通过 for 循环并匹配从输入字段发送的名称并将它们匹配到 $_FILES(PHP Superglobal,对不起,我不知道 ruby​​ 文件变量)变量来完成此操作。

我的意思是您可以在提交前检查文件。我这样做,然后在用户提交表单之前将其输出给用户,让他们知道他们上传到我的网站的内容。任何不符合标准的内容都不会显示给用户,因此他们应该知道,太大的文件不会被保存。这应该适用于所有浏览器,因为我没有使用 FormData 对象。

【讨论】:

  • 您不能在客户端执行它并期望它始终有效。如果服务器端的检查也很重要,否则人们将使用表单的修改副本(或其他客户端方式)来上传超大文件。服务器端检查就像一把锁,客户端检查就像一张写着“禁止进入”的便利贴。先锁门,再贴“禁止入内”标志。
  • @user340140 只要客户端支持javascript就可以。如果客户端不只是简单地声明该站点需要启用 javascript。 Javascript 有一个文件阅读器,基本上不会被欺骗,它会一点一点地读取,所以不用担心会收到一个秘密的另一个大小的小文件。服务器端是首选的“安全”方法,但在谈到文件大小时,我看不出 javascript 的安全性如何。
  • 因为就像 user340140 所说的那样,无论你做什么,Javascript 都可以轻松修改。您可以在服务器端检查可用性的基础上执行此操作,但您无法使用客户端 Javascript 来保护它。
  • 只使用 JavaScript(客户端)代码是不可行的,因为它很容易被绕过。需要一个服务器端逻辑。
  • 虽然服务器端应始终进行最终验证,但在客户端进行也将限制不希望绕过检查并启用 Javascript 的任何人的错误上传数量 - 这通常表示大量用户,如果您同时实现面向用户和服务器部分。
【解决方案2】:
var uploadField = document.getElementById("file");

uploadField.onchange = function() {
    if(this.files[0].size > 2097152){
       alert("File is too big!");
       this.value = "";
    };
};

这个例子应该可以正常工作。我将其设置为大约 2MB,1MB 字节为 1,048,576,因此您可以将其乘以您需要的限制。

这里是更清晰的 jsfiddle 示例:
https://jsfiddle.net/7bjfr/808/

【讨论】:

  • 只使用 JavaScript(客户端)代码是不可行的,因为它很容易被绕过。需要一个服务器端逻辑。
  • @AkshayAnurag 客户端验证防止浪费客户端的时间和服务器的带宽,它与安全无关,而是关于用户体验
  • @AkshayAnurag 您只能在上传整个图像后在后端检查图像大小,如果这是一个巨大的图像,假设 16mb 并且客户端的连接速度比用户必须一直等待的慢图片正在上传只是为了在最后得到一个错误。为了防止发生类似的事情,您需要在前端进行某种验证。如果我错了或遗漏了什么,或者您有什么可以防止这种情况发生,请告诉我?
  • @AkshayAnurag 如果“有更好的方法”,您应该发布自己的答案。
【解决方案3】:

您不能在客户端执行此操作。您必须在服务器上执行此操作。

编辑:这个答案已经过时了!

当我在 2011 年最初回答这个问题时,HTML File API 只是一个草稿。 It is now supported on all major browsers.

我会提供解决方案的更新,但@mark.inman.winning has already answered better than I could

请记住,即使现在可以在客户端验证,您仍然应该在服务器上验证它。可以绕过所有客户端验证。

【讨论】:

  • 是的,现在不可能。 HTML5 中有一些新文件 api 的草稿,但目前没有浏览器完全支持它。
  • 请参阅:cs.tut.fi/~jkorpela/forms/file.html,“设置文件大小限制”,了解为什么在客户端尝试这样做毫无意义。
  • 您无法访问访问者计算机上的本地文件系统,最好的办法是让 apache 限制文件大小并在文件太大时停止上传。跨度>
  • 在客户端这样做是愚蠢的——除非你只是想让它方便用户。 “您必须验证服务器端。您可以验证客户端。”
  • 有趣...这似乎有效:plupload.com。唯一的问题是没有flash、silverlight、gears等插件的IE8似乎会默认为HTML4。
【解决方案4】:

const input = document.getElementById('input')

input.addEventListener('change', (event) => {
  const target = event.target
  	if (target.files && target.files[0]) {

      /*Maximum allowed size in bytes
        5MB Example
        Change first operand(multiplier) for your needs*/
      const maxAllowedSize = 5 * 1024 * 1024;
      if (target.files[0].size > maxAllowedSize) {
      	// Here you can ask your users to load correct file
       	target.value = ''
      }
  }
})
&lt;input type="file" id="input" /&gt;

如果您需要验证文件类型,请在下面的 cmets 中写入,我将分享我的解决方案。

(剧透:accept 属性不是防弹解决方案)

【讨论】:

    【解决方案5】:

    视频文件示例(HTML + Javascript):

    function upload_check()
    {
        var upl = document.getElementById("file_id");
        var max = document.getElementById("max_id").value;
    
        if(upl.files[0].size > max)
        {
           alert("File too big!");
           upl.value = "";
        }
    };
    <form action="some_script" method="post" enctype="multipart/form-data">
        <input id="max_id" type="hidden" name="MAX_FILE_SIZE" value="250000000" />
        <input onchange="upload_check()" id="file_id" type="file" name="file_name" accept="video/*" />
        <input type="submit" value="Upload"/>
    </form>

    【讨论】:

      【解决方案6】:

      这个问题是很久以前的问题,但也许这可以帮助那些正在苦苦挣扎的人。 如果您正在使用表单,最简单的方法是创建一个新的 FormData 用你的表格。例如:

      form.addEventListener("submit", function(e){
        e.preventDefault()
      
        const fd = new FormData(this)
      
        for(let key of fd.keys()){
      
          if(fd.get(key).size >= 2000000){
            return console.log(`This archive ${fd.get(key).name} is bigger than 2MB.`)
          }
      
          else if(fd.get(key).size < 2000000){
            console.log(`This archive ${fd.get(key).name} is less than 2MB.`)
          }
      
          else{
            console.log(key, fd.get(key))
          }
      
        }
      
        this.reset()
      })
      

      如您所见,您可以通过键入以下内容从随表单提交的存档中获取大小:

      fd.get(key).size
      

      而且文件名也是可达的:

      fd.get(key).name
      

      希望这对您有所帮助!

      【讨论】:

        【解决方案7】:

        我只使用 JavaScript 做了一个解决方案,它支持多个文件:

        const input = document.querySelector("input")
        const result = document.querySelector("p")
        
        const maximumSize = 10 * 1024 * 1024 // In MegaBytes
        
        input.addEventListener("change", function(e){
            const files = Array.from(this.files)
            const approvedFiles = new Array
        
            if(!files.length) return result.innerText = "No selected files"
        
            for(const file of files) if(file.size <= maximumSize) approvedFiles.push(file)
        
            if(approvedFiles.length) result.innerText = `Approved files: ${approvedFiles.map(file => file.name).join(", ")}`
            else result.innerText = "No approved files"
        })
        <input type="file" multiple>
        <p>Result</p>

        【讨论】:

          【解决方案8】:

          用于验证主机大小的 PHP 解决方案。

          <?php
                  
              if ($_FILES['name']['size'] > 16777216) {
                          
              ?>
                      
                  <script type="text/javascript">
                          alert("The file is too big!");
                          location.href = history.back();
                  </script>
                      
              <?php
                  
                  die();
                  
              }
                 
          ?>
          

          16777216 字节 = 16 兆字节

          转换单位:https://convertlive.com/u/convert/megabytes/to/bytes#16

          改编自https://www.php.net/manual/en/features.file-upload.php

          【讨论】:

            【解决方案9】:
            <script type="text/javascript">
                $(document).ready(function () {
            
                    var uploadField = document.getElementById("file");
            
                    uploadField.onchange = function () {
                        if (this.files[0].size > 300000) {
                            this.value = "";
                            swal({
                                title: 'File is larger than 300 KB !!',
                                text: 'Please Select a file smaller than 300 KB',
                                type: 'error',
                                timer: 4000,
                                onOpen: () => {
                                    swal.showLoading()
                                    timerInterval = setInterval(() => {
                                        swal.getContent().querySelector('strong')
                                            .textContent = swal.getTimerLeft()
                                    }, 100)
                                },
                                onClose: () => {
                                    clearInterval(timerInterval)
            
                                }
                            }).then((result) => {
                                if (
                                    // Read more about handling dismissals
                                    result.dismiss === swal.DismissReason.timer
            
            
                                ) {
            
                                    console.log('I was closed by the timer')
                                }
                            });
            
                        };
                    };
            
            
            
                });
            </script>
            

            【讨论】:

            • 请尝试在您的代码中添加一些解释。
            • 只使用 JavaScript(客户端)代码是不可行的,因为它很容易被绕过。需要一个服务器端逻辑。
            猜你喜欢
            • 1970-01-01
            • 2011-01-29
            • 2017-03-09
            • 2011-01-13
            • 1970-01-01
            • 2022-10-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多