Skip to content

获取文件/文件结构(封装集合)

获取文件示例

vue
<template>
<input type="file" ref="InputDom" accept="image/jpeg, image/png, image/gif, image/jpg, image/gif, image/webp" @change="monitorFile($event)" style="display: none;">
</template>

<script>
import { ref } from 'vue';

// 获取dom元素
const InputDom = ref<HTMLInputElement>();

// 选择文件后接收文件
const monitorFile = (e: Event) => {
  const el = e.target as HTMLInputElement;
  console.log(el.files);
}
</script>

注意事项

如果是拖动某一些文件到特定区域,如:文件上传,拖动文件到div上;

一定要阻止【默认行为】,要不然浏览器会跳转新窗口打开文件;

拖动到div的文件,使用事件对象获取,从 dataTransfer 中获取文件列表【e.dataTransfer.files】

ts
@dragover.prevent 和 @drop.prevent="monitorFile($event)" // 重要

input选择文件属性

TIP

1.选择多个文件【不写就是默认选择一个】:

multiple="true" 属性 【或】 multiple="multiple" 属性 ==> 开启选择多个文件

vue
<input type="file" multiple="true"/>
<!-- 或 -->
<input type="file" multiple="multiple"/>

2.选择文件夹: webkitdirectory mozddirectory oddirectory 兼容属性(个必填)只能选择文件夹

vue
<input type="file" multiple="true" webkitdirectory mozddirectory oddirectory/>
  1. 限制选择文件属性accept

    一. 【使用 MIME 类型(推荐)】:

    1). 所有图片:accept="image/*";

     特定图片格式:accept="image/jpeg, image/png, image/gif"
    

    2). 所有视频:accept="video/*"

     特定视频格式:accept="video/mp4, video/webm"
    

    3). 所有音频:accept="audio/*";

    4). PDF 文档:accept="application/pdf";

    二. 【使用文件扩展名】:

    1). 限制特定后缀:accept=".jpg, .png, .pdf"

    2). 混合使用:accept=".doc, .docx, application/pdf"

    三. 【混合使用】

    1). accept="image/*, .pdf, application/msword" (接受所有图片、PDF文件以及旧版Word文档)

获取移动到元素上的的方法

ts
<html元素>.ondragstart => (e.preventDefault()) // 开始拖动元素时触发
<html元素>.ondrag => (e.preventDefault()) // 拖动过程中持续触发
<html元素>.ondragend => (e.preventDefault()) // 拖动结束时触发(无论成功失败)
<html元素>.ondragenter => (e.preventDefault()) // 文件移进后触发
<html元素>.ondragover => (e.preventDefault()) // 文件移动触发
<html元素>.ondragleave => (e.preventDefault()) // 离开目标元素时触发【离开移动区域】
<html元素>.ondrop => (e.preventDefault()) // 文件放下后触发

获取数据结构

ts
// 获取数据结构 (移动到div上)
export const getFiles = (res) => {
    return new Promise(async (response) => {
        response(await getFile(res));
        async function getFile(entry: any) {
            // console.log(entry.name);
            if (entry.name === "node_modules" || entry.name === "miniprogram_npm")
                return {
                    // 文件
                    type: "files",
                    // 开关节流阀
                    isFLag: false,
                    // 后缀名
                    typeName: 'files',
                    // 文件名
                    name: entry.name,
                    // 种类, 性质, 方式
                    fullPath: entry.fullPath,
                    // file文件
                    file: [],
                };

            if (entry.isFile) {
                // 表示是一个文件
                return {
                    // 文件
                    type: "file",
                    // 开关节流阀
                    isFLag: false,
                    // 后缀名
                    typeName: entry.name.split(".").pop().toLocaleLowerCase(),
                    // 文件名
                    name: entry.name,
                    // 种类, 性质, 方式
                    fullPath: entry.fullPath,
                    // file文件
                    file: await callhander(entry),
                };
            } else {
                // 表示是一个文件夹列表
                let files: any = await hander(entry);
                return {
                    // file文件
                    files,
                    // 文件
                    type: "files",
                    // 开关节流阀
                    isFLag: false,
                    // 后缀名
                    typeName: 'files',
                    // 文件名
                    name: entry.name,
                    // 种类, 性质, 方式
                    fullPath: entry.fullPath,
                    // 提示信息
                    msg: files.length ? "many file" : `“${entry.name}”为空`,
                };
            }
        }

        // 创建异步迭代器
        function hander(entry) {
            return new Promise((res) => {
                let arr = [];
                // 表示是一个文件夹列表
                const reader = entry.createReader();
                reader.readEntries(async (en) => {
                    if (!en.length) res(arr);
                    for (const el of en) {
                        arr.push(await getFile(el));
                        if (arr.length == en.length) {
                            res(arr);
                        }
                    }
                });
            });
        }
    });

    // item为遍历每一项的FileEntry对象,调用 原型上的 file 方法使其转换为file对象 通过回调函数的方法返给调用者
    function callhander(item: any) {
        return new Promise((res) => {
            // 把转换的结构暴露出
            item.file((r: any): void => res(r));
        });
    }
}

点击上传按钮 (提取所有文件)

ts
// 点击上传按钮(提取所有文件)
export const getHander = (target: any) => {
    return new Promise(response => {
        response({
            // 文件名称
            name: target[0].webkitRelativePath.split("/")[0],
            // 默认是否打开
            isFLag: false,
            // 提示信息
            msg: "many file",
            // 文件类型
            type: "files",
            // 图标类型
            typeName: "files",
            // 文件集合
            files: [...target].reduce((val, item) => {
                return [
                    ...val,
                    {
                        // 文件名称
                        name: item.name,
                        // 默认是否打开
                        isFLag: false,
                        // 提示信息
                        msg: "ok",
                        // 文件类型
                        type: "file",
                        // 图标类型
                        typeName: item.name.split(".").pop(),
                        // file文件
                        file: item,
                    },
                ];
            }, []),
        })
    });
}

读取器读取的文件目录

ts
 // 打开文件内容
let res: any = await window.showDirectoryPicker();
// 获取文件内容
const root: any = await getFolder(res);
console.log(root);




// 获取文件结构
function getFolder(res) {
  return new Promise((response) => {
    response(fn(res));

    async function fn(handle: any) {
      if (handle.kind === "file") {
        return {
          // 文件
          type: "file",
          // 开关节流阀
          isFLag: false,
          // 后缀名
          typeName: handle.name.split(".").pop().toLocaleLowerCase(),
          // 文件名
          name: handle.name,
          // 句柄
          handle,
          // 种类, 性质, 方式
          kind: handle.kind,
        };
      }

      // 添加判断node_modules模块,直接返回该模块文件夹
      if (handle.name === "node_modules" || handle.name === "miniprogram_npm") {
        return {
          // 文件
          type: "files",
          // 开关节流阀
          isFLag: false,
          // 后缀名
          typeName: "files",
          // 文件名
          name: handle.name,
          // 种类, 性质, 方式
          kind: handle.kind,
          // 文件列表
          files: handle.files,
          // 句柄
          handle,
        };
      }

      handle.files = [];
      // 得到异步迭代器
      const inter = handle.entries();
      for await (const item of inter) {
        handle.files.push(await getFolder(item[1]));
      }
      return {
        // 文件
        type: "files",
        // 开关节流阀
        isFLag: false,
        // 后缀名
        typeName: "files",
        // 文件名
        name: handle.name,
        // 种类, 性质, 方式
        kind: handle.kind,
        // 文件列表
        files: handle.files,
        // 句柄
        handle,
      };
    }
  });
}

创建读取器

ts
// 创建读取对象
const reader = new FileReader();

// 音频读取
reader.readAsDataURL('音频file文件');
reader.onload = (e) => {
  console.log({
    status: 200,
    msg: `读取成功`,
    type: "img",
    data: {
      src: e.target.result,
    },
  })
};

// 读取文本
// 文本自动读取
reader.readAsText('文件发file文件', "UTF-8");
reader.onload = (e) => {
  // 默认配置
  console.log({
    status: 200,
    msg: `读取成功`,
    type "text",
    data: {
      e.target.result
    },
  })
};

Copyright © 2026 Luke