JavaScript文件上传大小验证

366

有没有一种方法可以使用JavaScript在上传文件之前检查文件大小?


我在使用Chrome时遇到了类似的问题。我只是关闭了当前标签页并打开了一个新的。 - bandito40
15个回答

432

是的,你可以使用 File API 实现此功能。

以下是一个完整的示例(请参阅注释):

document.getElementById("btnLoad").addEventListener("click", function showFileSize() {
    // (Can't use `typeof FileReader === "function"` because apparently it
    // comes back as "object" on some browsers. So just see if it's there
    // at all.)
    if (!window.FileReader) { // This is VERY unlikely, browser support is near-universal
        console.log("The file API isn't supported on this browser yet.");
        return;
    }

    var input = document.getElementById('fileinput');
    if (!input.files) { // This is VERY unlikely, browser support is near-universal
        console.error("This browser doesn't seem to support the `files` property of file inputs.");
    } else if (!input.files[0]) {
        addPara("Please select a file before clicking 'Load'");
    } else {
        var file = input.files[0];
        addPara("File " + file.name + " is " + file.size + " bytes in size");
    }
});

function addPara(text) {
    var p = document.createElement("p");
    p.textContent = text;
    document.body.appendChild(p);
}
body {
    font-family: sans-serif;
}
<form action="#" onsubmit="return false;">
    <input type="file" id="fileinput">
    <input type="button" id="btnLoad" value="Load">
</form>


略微偏离主题,但请注意客户端验证不能替代服务器端验证。客户端验证纯粹是为了提供更好的用户体验。例如,如果您不允许上传超过5MB的文件,您可以使用客户端验证来检查用户选择的文件大小是否超过5MB,并在大小超限时向他们提供友好的提示信息(这样他们就不会浪费时间上传文件,最后得到结果被服务器丢弃),但是您必须在服务器上强制执行此限制,因为所有客户端限制(和其他验证)都可以被规避。

21
支持“所有客户端限制(和其他验证)都可以被规避”的说法,对于“本地”/“编译”的数据库前端应用程序同样适用。不要将数据库访问密码放在编译后的代码中,甚至不要使用“加密”的方式保存(密码也在代码中 - 最近刚看到这种情况)。 - masterxilo

144

使用jQuery:

$('#image-file').on('change', function() {
  console.log('This file size is: ' + this.files[0].size / 1024 / 1024 + "MiB");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form action="upload" enctype="multipart/form-data" method="post">

  Upload image:
  <input id="image-file" type="file" name="file" />
  <input type="submit" value="Upload" />


</form>


3
@ipd,有没有可能提供IE8的后备方案?(我甚至为提到IE而自责) - Asher
2
这个很好用,但它也适用于多个文件吗? - Ingus
7
如果按照“1024”为基数计算,应该使用“MiB”。 - slartidan

139

适用于动态和静态文件元素

Javascript 只是解决方案

function validateSize(input) {
  const fileSize = input.files[0].size / 1024 / 1024; // in MiB
  if (fileSize > 2) {
    alert('File size exceeds 2 MiB');
    // $(file).val(''); //for clearing with Jquery
  } else {
    // Proceed further
  }
}
<input onchange="validateSize(this)" type="file">


2
好答案。我也遇到了同样的问题,但你的解决方案对我有用 :) - Dipankar Das
1
NB OP编辑了帖子,所以代码现在是正确的,使用size属性。 - UsAndRufus
1
谢谢你的回答,我差不多也是这么做的,只不过有一个改变。原来是 $(obj).files[0].size/1024/1024;,但现在改成了 obj.files[0].size/1024/1024; - Shakir Baba
有没有一种方法可以扩展宽度和高度验证?(以“文件”为起点,假设它是指图像) - jlmontesdeoca
@jlmontesdeoca 我认为你可以利用canvas读取文件并在此处获取其高度和宽度。 - Arun Prasad E S

29

这很简单。

const oFile = document.getElementById("fileUpload").files[0]; // <input type="file" id="fileUpload" accept=".jpg,.png,.gif,.jpeg"/>

if (oFile.size > 2097152) // 2 MiB for bytes.
{
  alert("File size must under 2MiB!");
  return;
}

15

如果您正在使用jQuery Validation,您可以编写类似以下内容的代码:

$.validator.addMethod(
  "maxfilesize",
  function (value, element) {
    if (this.optional(element) || ! element.files || ! element.files[0]) {
      return true;
    } else {
      return element.files[0].size <= 1024 * 1024 * 2;
    }
  },
  'The file size can not exceed 2MiB.'
);

14

我做了类似这样的东西:

$('#image-file').on('change', function() {
  var numb = $(this)[0].files[0].size / 1024 / 1024;
  numb = numb.toFixed(2);
  if (numb > 2) {
    alert('to big, maximum is 2MiB. You file size is: ' + numb + ' MiB');
  } else {
    alert('it okey, your file has ' + numb + 'MiB')
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<input type="file" id="image-file">


这句话说JavaScript,JQuery不在标签中。 - Hello234

14

是的,使用较新的浏览器中的文件API可以实现。有关详细信息,请参见TJ的答案。

如果您需要支持旧版浏览器,则必须使用基于Flash的上传程序,例如SWFUploadUploadify

SWFUpload功能演示展示了file_size_limit设置的工作原理。

请注意,这需要Flash,并且它的工作方式与普通上传表单略有不同。


11
尽管这个问题已经得到解答,我仍然想要发布我的答案。对于未来的观众可能会很有用。你可以像下面的代码一样使用它。
document.getElementById("fileinput").addEventListener("change",function(evt) {
  //Retrieve the first (and only!) File from the FileList object
  var f = evt.target.files[0];
  if (f) {
    var r = new FileReader();
    r.onload = function(e) {
      var contents = e.target.result;
      alert("Got the file\n" +
        "name: " + f.name + "\n" +
        "type: " + f.type + "\n" +
        "size: " + f.size + " bytes\n" +
        "starts with: " + contents.substr(1, contents.indexOf("\n"))
      );
      if (f.size > 5242880) {
        alert('File size Greater then 5MiB!');
      }


    }
    r.readAsText(f);
  } else {
    alert("Failed to load file");
  }
})
<input type="file" id="fileinput" />


2
点赞仅因为你让我省下了5分钟计算5MB有多少字节的时间;-) - David Fariña

3
我使用了一个主要的JavaScript函数,这个函数是我在Mozilla开发者网络网站上找到的 (https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications),还有另一个用于AJAX的函数,根据我的需要进行了修改。它接收一个文档元素ID,用于指定我要写入文件大小的HTML代码位置。
<Javascript>

function updateSize(elementId) {
    var nBytes = 0,
    oFiles = document.getElementById(elementId).files,
    nFiles = oFiles.length;

    for (var nFileId = 0; nFileId < nFiles; nFileId++) {
        nBytes += oFiles[nFileId].size;
    }
    var sOutput = nBytes + " bytes";
    // optional code for multiples approximation
    for (var aMultiples = ["K", "M", "G", "T", "P", "E", "Z", "Y"], nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
        sOutput = " (" + nApprox.toFixed(3) + aMultiples[nMultiple] + ")";
    }

    return sOutput;
}
</Javascript>

<HTML>
<input type="file" id="inputFileUpload" onchange="uploadFuncWithAJAX(this.value);" size="25">
</HTML>

<Javascript with XMLHttpRequest>
document.getElementById('spanFileSizeText').innerHTML=updateSize("inputFileUpload");
</XMLHttpRequest>

干杯


3

这个帖子中提供的 JQuery 示例过时了,而且谷歌也没有提供有用的信息,所以我进行了修订:

<script type="text/javascript">
  $('#image-file').on('change', function() {
    console.log($(this)[0].files[0].name+' file size is: ' + $(this)[0].files[0].size/1024/1024 + 'Mb');
  });
</script>

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