文件上传 还在用 input 标签?

11,614

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

文件上传

input 标签方式

这个是我们现在目前常用的一种上传方式,就是通过在页面放置 input 标签,并且 type 类型为 file

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

image.png

有几个属性

  • accept

    如果没有设置的话,任何类型的文件都可以进行上传

    image.png

    可以设置的属性有很多,查看 MDN 文档,这里有常见的 Common MIME types 的属性

  • capture (这个没怎么用)

    这有两个值

    • user 代表前置摄像头

    • environment 代表后置摄像头

  • multiple

    这个属性 开启的话,就可以选取多个文件

  • webkitdirectory

    添加了这个属性后,就可以用于选择 文件夹

        <input type="file" name="" id="" webkitdirectory>
    

    与上面的图进行对比,可以看到明显的差别。

    image.png

js方式

为什么说是 js 方式?

因为 我们是通过 某种方式,触发 下面 js 中的这几个 API,来达到我们上传文件的一个功能。与html无关。

window.showOpenFilePicker()window.showSaveFilePicker()window.showDirectoryPicker()。查看下它们的 MDN 的文档

  • window.showOpenFilePicker()

    代表选中文件,下面是代码

        <span @click="clickFunc">请点我</span>
    
        const clickFunc = async () => {
          const options = {
            types: [
              {
                description: '这只是一个描述',
                accept: {
                  // 'image/*': ['.png', '.gif', '.jpeg', '.jpg'],
                  // "text/plain": [".txt"],
                  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx']
                }
              }
            ],
            excludeAcceptAllOption: false // 有一个选项的按钮
            // multiple: true
          }
          try {
            myFiles.file = await window.showOpenFilePicker(options)
          } catch (error) {
            console.error(error)
          }
        }
    

    相关 options 的属性

    • excludeAcceptAllOption

      上面代码中 options 里的一个配置 excludeAcceptAllOption

      • 这个值如果是 false

        则显示下图中的这个选项按钮,并且能看看到 格式 的 一个 描述信息。

      • 这个值如果是true

        这不显示 这个按钮

    • myltiple

      多选的意思,能够选取多个文件

    • type

      这个通过 accept 来以 键值对的形式来接受,值为 数组 类型。

    image.png

    点击按钮,选中下面这个 表格.xlsx

    image.png

    代码添加 log 信息,查看文件的详细信息,在控制台查看。

        console.log(myFiles.file)
        console.log(myFiles.file[0])
        console.log(myFiles.file[0].getFile()) // 会返回一个 promise
        // 所以我们需要 await 来接受
        console.log(await myFiles.file[0].getFile());
    
    

    image.png

  • window.showSaveFilePicker()

    保存文件,这里简单写了下,具体的使用方法,还需深入了解*。

        const clickFunc = async () => {
          const options = {
            types: [
              {
                description: '这只是一个描述',
                accept: {
                  // "text/plain": [".txt"],
                  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx']
                }
              }
            ],
          }
          try {
            myFiles.file = await window.showSaveFilePicker(options)
            console.log(myFiles.file)
            // console.log(myFiles.file)
            console.log(myFiles.file.getFile()) // 返回一个 promise
            // // 所以我们需要 await 来接受
            // console.log(await myFiles.file[0].getFile());
    
          } catch (error) {
            console.error(error)
          }
        }
    

    点击后产生一个 存储 的一个弹窗,可以修改里面的文件名,默认是 未命名。

    后缀名是根据你 options 里面 配置的 accept 来决定的。如果 accept 里面有多个属性,那么默认后缀名为 键值对中的第一个。

    image.png

    image.png

    保存后的 该文件的 具体信息,可以看到是一个空的文件。说明后续保存,还需深入了解*。

    image.png

  • window.showDirectoryPicker()

    这个 API 代表的是 选中 文件夹,如下图

    image.png

    我们重新处理下代码,并且可以查看 文件夹 里面的文件信息。

      ```js
          const clickFunc = async () => {
            try {
              myFiles.file = await window.showDirectoryPicker()
              console.log(myFiles.file)
              console.log(myFiles.file.values())
    
              for await (const item of myFiles.file.values()) {
                console.log(item)
              }
            } catch (error) {
              console.error(error)
            }
          }
      ```
    

    注意 此时 浏览器 为了安全的一个着想,让我们在页面上,手动确定查看文件。

    image.png

    这样就可以看到我们选中的 文件夹 里面的 文件的简单信息。

    image.png

    从上图可以查看到有个 getFile() 这个属性,我们更改一下代码,查看每个文件里面的详细信息,方便我们做后续的处理

        for await (const item of myFiles.file.values()) {
          console.log(item)
          console.log(await item?.getFile())
          console.log('  ')
        }
    

    image.png

总结

这是一个全新的 通过 js 方式进行上传文件的一个操作。

抛弃了原本必须通过 input type="file" 的一个形式。

可以大大提高 项目股的 可拓展性 以及 使用的场景。


补充

这几个 API 由于是新的,所以如果用的话,还是要考虑兼容性的。在这里补充一份 兼容性的 网站 及 对应图片,供大家查看。

image.png