We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

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

<input name="myFile" type="file">

Value DOMString 选择文件的路径
事件 change 事件 input
支持的常用属性 accept, multiple, required
IDL 属性 文件 和 值
方法 select()

Value

文件输入的 value 属性包括了一个 value 表示选择文件的路径DOMString

Note:
  1. 如果选择了多个文件, 这个值表示第一个被选择的文件路径. JavaScript 可以通过 Input 的 FileList 属性获取到其他的文件路径.
  2. 没有选择文件该值为空字符串. 
  3. 为了阻止恶意软件猜测文件路径, 该值 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>

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

Note: 通过 Github / 在线运行 -- source code / see it running live.

忽略用户操作系统/设备的影响, 文件 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" or accept=".png" — 只接受 png 图片.
  • accept="image/png, image/jpeg" or 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>

这个例子的结果和上面的例子相似. 

Note: 在 Github 上查看源码 / 在运行 --  source code / running live.

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

Screenshot of a macOS file picker dialog. Files other than JPEG are grayed-out and unselectable.

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

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

更多例子

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

Note: 查看更完整的例子 file-example.html / see it live also

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';
  }
}

运行一下:

规范

Specification Status Comment
HTML Living Standard
<input type="file">
Living Standard Initial definition
HTML 5.1
<input type="file">
Recommendation Initial definition

浏览器兼容性

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Feature Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
Basic support 1.0 ? 1.0 (1.7 or earlier) (Yes) 1.0 1.0
Feature Android Chrome for Android Edge Firefox Mobile (Gecko) IE Mobile Opera Mobile iOS WebKit
(Safari/Chrome/Firefox/etc)
Basic support (Yes) (Yes) (Yes) 4.0 (4.0) (Yes) (Yes) (Yes)

另见

文档标签和贡献者

最后编辑者: AmyFoxFN,