阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      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

      目录
      目录