HTML input type file 类型

🌙
手机阅读
本文目录结构

功能介绍

<input> type 类型为 file 的 input 元素使得用户可以选择一个或多个元素以提交表单的方式上传到服务器上,或者通过 Javascript 的 File API 对文件进行操作 .

文件输入的 value 属性包括了一个 value 表示选择文件的路径DOMString。如果用户选择了多个文件,则该值表示他们选择的文件列表中的第一个文件。

可以使用输入的HTMLInputElement.files属性标识其他文件。

Note:

  • 如果选择了多个文件, 这个值表示第一个被选择的文件路径。JavaScript 可以通过 Input 的 FileList 属性获取到其他的文件路径。
  • 没有选择文件该值为空字符串。
  • 为了阻止恶意软件猜测文件路径, 该值 以 C:\fakepath\为前缀。

如何使用

A basic example

<form>
 <div>
   <label for="file">Choose file to upload</label>
   <input type="file" id="file" name="file" multiple>
 </div>
 <div>
   <button>Submit</button>
 </div>
</form>

上述代码会产生如下结果:

忽略用户操作系统/设备的影响, 文件 input 提供了一个按钮去打开文件选择窗口.

包括上面所说的 multiple 属性, 多个文件可以被同时选中. 只要用户所在的平台允许 (e.g. 摁住 Shift 或者 Control), 用户可以选择多个文件. 如果不希望多选, 忽略 multiple 属性.

在上面的例子中, 当表单被提交, 每个选中的文件名将被添加到 URL 参数中?file=file1.txt&file=file2.txt

获取选中文件的信息

选中文件通过 HTMLInputElement.files 属性返回 — 返回值是一个 FileList 对象,这个对象是一个包含了许多 File 文件的列表(你也可以像列表一样操作它).

每个 File 对象包含了下列信息:

  • name: 文件名.
  • lastModified: UNIX timestamp 形式的最后修改时间.
  • lastModifiedDate: Date 形式的最后修改时间.
  • size: 文件的字节大小.
  • type: DOMString 文件的 MIME 类型.

限制允许的文件类型

如果你不希望用户上传任何类型的文件, 你可以使用 input 的 accept 属性.

accept 属性接受一个逗号分隔的 MIME 类型字符串, 如:

  • accept=“image/png” 或 accept=".png" — 只接受 png 图片.
  • accept=“image/png, image/jpeg” 或 accept=".png, .jpg, .jpeg" — PNG/JPEG 文件.
  • accept=“image/*” — 接受任何图片文件类型.
  • accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document" — 接受任何 MS Doc 文件类型.

下面是一个更完整的例子:

<form>
  <div>
    <label for="profile_pic">Choose file to upload</label>
    <input type="file" id="profile_pic" name="profile_pic"
          accept=".jpg, .jpeg, .png">
  </div>
  <div>
    <button>Submit</button>
  </div>
</form>

这个例子和上面例子的不同在于你可以选择的文件类型是固定的, 在文件选择其中你只能看到被允许选中的类型.

accept 属性并不会验证选中文件的类型. 他只是为开发这提供了一种引导用户做出期望行为的方式而已, 用户还是有办法绕过浏览器的限制.

因此, 在服务器端进行文件类型验证是必不可少的.

更多例子

在这个例子中, 我们将展示利用 HTMLInputElement.files 进行文件选择的更高级用法.

HTML 代码

<form>
  <div>
    <label for="image_uploads">Choose images to upload (PNG, JPG)</label>
    <input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
  </div>
  <div class="preview">
    <p>No files currently selected for upload</p>
  </div>
  <div>
    <button>Submit</button>
  </div>
</form>

就像我们之前做的那样.

接下来, 看一下 JavaScript 代码.

// 获取 input 元素
var input = document.querySelector('input');
// 获取 preview 元素
var preview = document.querySelector('.preview');
// 将 input 变成透明的
input.style.opacity = 0;

Note: 使用 opacity 而不是 visibility: hidden / display: none的原因是因为visibility和display会让input不可选择

接下来, 我们监听 input 的 change 事件, 并且在事件发生的时候调用 updateImageDisplay 方法.

input.addEventListener('change', updateImageDisplay);

当 updateImageDisplay 方法被调用, 我们:

  • 使用 while 循环清空 preview 中的内容.
  • 获取 the FileList 对象并且将选中文件保存到 curFiles 变量中.
  • 检查是否没有选中文件.
  • 在 preview 中打印所有选中文件的信息:
  • 使用自定义的 validFileType() 检查文件类型是否正确.
    • 正确:
      • 在 div 中打印文件名称和 size.
      • 通过 window.URL.createObjectURL(curFiles[i]) 以及 css 产生预览图.
    • 不正确: 告诉用户.
function updateImageDisplay() {
  while(preview.firstChild) {
    preview.removeChild(preview.firstChild);
  }

  var curFiles = input.files;
  if(curFiles.length === 0) {
    var para = document.createElement('p');
    para.textContent = 'No files currently selected for upload';
    preview.appendChild(para);
  } else {
    var list = document.createElement('ol');
    preview.appendChild(list);
    for(var i = 0; i < curFiles.length; i++) {
      var listItem = document.createElement('li');
      var para = document.createElement('p');
      if(validFileType(curFiles[i])) {
        para.textContent = 'File name ' + curFiles[i].name + ', file size ' + returnFileSize(curFiles[i].size) + '.';
        var image = document.createElement('img');
        image.src = window.URL.createObjectURL(curFiles[i]);

        listItem.appendChild(image);
        listItem.appendChild(para);

      } else {
        para.textContent = 'File name ' + curFiles[i].name + ': Not a valid file type. Update your selection.';
        listItem.appendChild(para);
      }

      list.appendChild(listItem);
    }
  }
}

自定义的 validFileType() 接受一个 File 对象作为参数, 然后检查文件类型是否在 accept 列表中.

var fileTypes = [
  'image/jpeg',
  'image/pjpeg',
  'image/png'
]

function validFileType(file) {
  for(var i = 0; i < fileTypes.length; i++) {
    if(file.type === fileTypes[i]) {
      return true;
    }
  }

  return false;
}

returnFileSize()方法接受一个数字作为参数以 KB/MB 的形式返回结果.

function returnFileSize(number) {
  if(number < 1024) {
    return number + 'bytes';
  } else if(number > 1024 && number < 1048576) {
    return (number/1024).toFixed(1) + 'KB';
  } else if(number > 1048576) {
    return (number/1048576).toFixed(1) + 'MB';
  }
}

参考网站:https://developer.mozilla.org/zh/docs/web/html/element/input/file

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了