您的位置:

input type file的使用详解

一、基本介绍

input type file 是HTML表单元素中用于上传文件的标签。它允许用户从本地设备中选择一个或多个文件作为它们想要上传的内容。

这个标签的type属性值为file,它由一个文件选择框和一个上传按钮组成,通过点击上传按钮或者按下回车键就可以上传文件了。

下面的代码段是最基本的input type file的用法:

    <form>
        <p>请选择文件</p>
        <input type="file">
        <input type="submit">
    </form>

二、accept属性

accept属性规定了上传文件时对文件的类型进行限定。如果使用accept属性,那么在文件选择器中,用户只能看到符合要求的文件类型。

accept属性有两种限制方式,一种是通过文件扩展名限制,一种是通过MIME类型限制。下面是一个MIME类型限制的示例代码:

    <input type="file" accept="image/*">

上述代码中 accept 属性的值为“image/*”,表示限制上传的文件类型必须是图像文件。通配符*表示匹配任何文件类型的图像,包括jpg、png、gif等。

三、multiple属性

multiple属性用于指定是否允许选择多个文件进行上传。该属性值为布尔类型。

如果使用multiple属性,那么文件选择器中会显示一个多选框,用户可以通过该多选框选择多个文件,从而将这些文件一次性上传。

下面是一个multiple属性的示例:

    <input type="file" multiple>

四、files属性

当用户通过input type file选择了文件后,浏览器会将文件作为File对象存储在files属性中。

我们可以使用JavaScript对文件进行处理,比如可以读取文件的二进制数据、上传文件等等。以下是一个简单的示例:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>读取文件数据</title>
    </head>
    <body>
      <input type="file" id="fileInput">
      <script>
        const fileInput = document.getElementById('fileInput');
        fileInput.addEventListener('change', (event) => {
          const file = event.target.files[0];
          const reader = new FileReader();
          reader.readAsText(file);
          reader.onload = () => {
            console.log(reader.result);
          };
        });
      </script>
    </body>
    </html>

上面的代码演示了如何在文件选择器选择文件,然后将文件的文本数据通过console.log()输出到浏览器控制台。

五、拓展

当然,以上只是input type file的基本使用方法,实际上,该标签还有很多值得探讨的方面,比如上传进度条的实现、多个input type file的处理、授权等等。

下面是一个完整的input type file示例,涵盖了基本的上传功能,上传进度条,文件列表展示等等。

  <!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>文件上传</title>
      <style>
        .progress {
          position: relative;
          width: 100%;
          height: 4px;
          background-color: #f5f5f5;
          border-radius: 2px;
          margin-top: 10px;
        }
        .progress .bar {
          position: absolute;
          left: 0;
          top: 0;
          height: 100%;
          background-color: #2d8cf0;
          border-radius: 2px;
          transition: width 0.3s linear;
        }
        .file-item {
          padding: 10px;
          border-bottom: 1px solid #eee;
          display: flex;
          align-items: center;
        }
        .file-item .file-info {
          flex: 1;
          margin-left: 10px;
        }
        .file-item .file-name {
          font-size: 16px;
          font-weight: bold;
        }
        .file-item .file-size {
          font-size: 12px;
          color: #ccc;
          margin-top: 5px;
        }
        .file-item .file-progress {
          display: flex;
          margin-top: 5px;
          align-items: center;
        }
        .file-item .file-progress .progress {
          width: 100px;
          height: 4px;
          margin-left: 10px;
          margin-right: 10px;
        }
        .file-item .file-progress .progress .bar {
          background-color: #f0ad4e;
        }
      </style>
    </head>
    <body>
      <form id="upload-form">
        <input type="file" name="file" id="file" multiple>
        <input type="button" value="选择文件">
        <input type="submit" value="上传">
      </form>
      <div id="file-list"></div>
      <script>
        const fileList = [];
        const form = document.getElementById('upload-form');
        const fileInput = document.getElementById('file');
        const fileListElm = document.getElementById('file-list');
        const btn = document.querySelector('input[type="button"]');
        const progressBar = document.createElement('div');
        const createFileItem = (file) => {
          const fileItem = document.createElement('div');
          const fileInfo = document.createElement('div');
          const fileName = document.createElement('div');
          const fileSize = document.createElement('div');
          const fileProgress = document.createElement('div');
          const progress = document.createElement('div');
          const bar = document.createElement('div');
          fileItem.className = 'file-item';
          if (file.type.startsWith('image/')) {
            const img = document.createElement('img');
            img.src = URL.createObjectURL(file);
            img.width = 100;
            img.height = 100;
            fileItem.appendChild(img);
          } else {
            const icon = document.createElement('i');
            icon.className = 'fa fa-file-o';
            fileItem.appendChild(icon);
          }
          fileInfo.className = 'file-info';
          fileName.className = 'file-name';
          fileSize.className = 'file-size';
          fileProgress.className = 'file-progress';
          progress.className = 'progress';
          bar.className = 'bar';
          fileName.innerText = file.name;
          fileSize.innerText = formatFileSize(file.size);
          fileItem.appendChild(fileInfo);
          fileInfo.appendChild(fileName);
          fileInfo.appendChild(fileSize);
          fileItem.appendChild(fileProgress);
          fileProgress.appendChild(progress);
          progress.appendChild(bar);
          fileListElm.appendChild(fileItem);
          return fileItem;
        };
        const handleFileSelect = (event) => {
          event.stopPropagation();
          event.preventDefault();
          const files = event.dataTransfer ? event.dataTransfer.files : event.target.files;
          for (const file of files) {
            const fileItem = createFileItem(file);
            fileList.push({
              file,
              fileItem,
              progressbar: new ProgressBar(fileItem.querySelector('.progress'), 0)
            });
          }
          form.classList.add('uploading');
        };
        const handleDragOver = (event) => {
          event.stopPropagation();
          event.preventDefault();
          event.dataTransfer.dropEffect = 'copy';
        };
        const uploadFile = (file, onProgress) => {
          const formData = new FormData();
          formData.append('file', file);
          const xhr = new XMLHttpRequest();
          xhr.open('POST', '/upload');
          xhr.upload.addEventListener('progress', ({loaded, total}) => {
            onProgress(loaded / total);
          });
          xhr.send(formData);
        };
        btn.addEventListener('click', () => {
          fileInput.click();
        });
        fileInput.addEventListener('change', handleFileSelect);
        form.addEventListener('dragover', handleDragOver);
        form.addEventListener('drop', handleFileSelect);
        form.addEventListener('submit', (event) => {
          event.preventDefault();
          for (const {file, fileItem, progressbar} of fileList) {
            progressbar.show();
            uploadFile(file, (progress) => {
              progressbar.update(progress);
            }).then(() => {
              progressbar.close();
              fileItem.querySelector('.file-name').style.textDecoration = 'line-through';
            });
          }
          fileList.length = 0;
          form.classList.remove('uploading');
        });
        class ProgressBar {
          constructor(elm, progress) {
            this.elm = elm;
            this.bar = elm.querySelector('.bar');
            this.progress = progress;
            this.update(progress);
          }
          update(progress) {
            this.progress = progress;
            this.bar.style.width = Math.round(this.progress * 100) + '%';
          }
          show() {
            this.elm.style.display = 'block';
          }
          close() {
            this.elm.style.display = 'none';
          }
        }
        function formatFileSize(size) {
          const units = ['B', 'KB', 'MB', 'GB'];
          let index = 0;
          while(size >= 1024 && index < units.length - 1) {
            size /= 1024;
            index++;
          }
          return size.toFixed(2) + units[index];
        }
      </script>
    </body>
  </html>

上述示例代码实现了基本的文件上传功能,包括单个文件上传和多个文件上传,上传进度条的展示,文件列表的展示等等。具体的细节解释可在代码中查看。