File System Access API 让浏览器拥有操作本地文件的能力

简介: File System Access API 让浏览器拥有操作本地文件的能力


在早期我们经常听到这样的说法:浏览器是一个沙盒,它不允许我们操作本地文件,但是现在这个说法已经不再适用了,因为我们可以使用 File System Access API 来实现这个功能。


什么是 File System Access API


File System Access API 是一项 Web API,允许 Web 应用程序从用户设备的本地文件系统中读取和写入文件。


它提供了一种简单且安全的方法,让用户在不离开 Web 应用的情况下,从本地文件系统中操作文件。


这项 APIWeb 应用程序提供了更多的灵活性和功能,使其更接近于本地应用程序的体验。


File System Access API 遵循同源策略,只允许 Web 应用程序在具有相同源的文件系统上进行操作。


当用户使用该 API 时,会提示用户授权应用程序访问他们的文件系统。


如果用户授权,则应用程序可以使用该 API 访问用户选择的文件和目录。


使用 File System Access API 可以访问本地文件系统,从而实现一些有用的功能,例如:


  • 将文件从本地文件系统上传到 Web 应用程序;
  • Web 应用程序中的数据写入到本地文件系统中;
  • 在用户的本地文件系统上创建、重命名和删除文件;
  • 读取本地文件系统上的文件内容。


如何使用 File System Access API


我不是很喜欢概念性的东西,上面的内容是网上借鉴的(文化人),我更喜欢直接上代码,所以我们直接上代码。


选择文件


首先我们来看看如何选择文件,这个功能是 File System Access API 中最基础的功能,我们可以通过 showOpenFilePicker 方法来实现。

const fileHandle = await window.showOpenFilePicker();
console.log(fileHandle);

可以看到我们这里使用了async/await语法,这是因为showOpenFilePicker异步方法,它会返回一个Promise对象,我们可以通过await来等待它的结果。


showOpenFilePicker方法会返回一个FileHandle对象,我们可以通过它来获取文件的信息。


我们来看看它最后返回的结果:

image.png

可以看到的是最后的结果是一个数组,这是因为我们可以选择多个文件;


而这个数组的每一项都是一个FileSystemFileHandle对象,我们可以通过它来获取和操作文件。


FileSystemFileHandle


FileSystemFileHandle对象是一个代表文件的对象,它提供了一些方法来获取和操作文件。


FileSystemFileHandle提供了一些方法来获取和操作文件,例如:


  • getFile:返回一个Promise对象,用于获取文件;
  • createSyncAccessHandle:返回一个FileSystemSyncAccessHandle对象,用于同步访问文件;
  • createWritable:返回一个Promise对象,用于创建一个可写流,用于写入文件;


我们来看看如何使用getFile方法来获取文件。

const fileHandle = await window.showOpenFilePicker();
const file = await fileHandle[0].getFile();
console.log(file);

image.png

可以看到,我们通过getFile方法获取到了文件,它返回的是一个File对象,我们可以通过它来获取文件的信息。


都拿到File对象了,后面怎么操作就很熟悉了吧,直接使用FileReader对象来获取文件内容,后面你爱怎么操作就怎么操作。


FileSystemHandle


通过截图我们还看到了有kind属性和name属性,这两个属性是继承自FileSystemHandle对象的。


FileSystemFileHandle继承自FileSystemHandle,它是一个代表文件系统中的文件或目录的对象。

FileSystemHandle提供了一些方法来获取和操作文件系统中的文件或目录,例如:


  • kind:返回一个字符串,用于表示文件或目录;
  • name:返回一个字符串,用于表示文件或目录的名称;
  • isSameEntry:返回一个boolean值,用于表示两个文件或目录是否相同;
  • queryPermission:返回一个Promise对象,用于查询文件或目录的权限;
  • requestPermission:返回一个Promise对象,用于请求文件或目录的权限;
  • remove:返回一个Promise对象,用于删除文件或目录;


我们可以通过kind属性来判断当前的FileSystemHandle对象是文件还是目录。

const fileHandle = await window.showOpenFilePicker();
const file = await fileHandle[0].getFile();
console.log(fileHandle[0].kind);

当然我们使用的是showOpenFilePicker方法,所以它返回的肯定是文件,所以还有一个showDirectoryPicker方法,它可以用来选择目录。


选择目录


选择目录的方法和选择文件的方法是一样的,只是我们需要使用showDirectoryPicker方法。

const directoryHandle = await window.showDirectoryPicker();
console.log(directoryHandle);

image.png

可以看到,我们通过showDirectoryPicker方法获取到了目录,它返回的是一个FileSystemDirectoryHandle对象,我们可以通过它来获取和操作目录。


使用showDirectoryPicker方法时,浏览器会提示用户授权应用程序访问他们的文件系统,请不要拒绝哟。


FileSystemDirectoryHandle


FileSystemDirectoryHandle对象是一个代表文件系统中的目录的对象,它提供了一些方法来获取和操作目录。


FileSystemDirectoryHandle提供的方法就比较多了,例如:


  • entries:返回一个AsyncIterable对象,用于获取目录中的所有文件和目录;
  • keys:返回一个AsyncIterable对象,用于获取目录中的所有文件和目录的名称;
  • values:返回一个AsyncIterable对象,用于获取目录中的所有文件和目录的FileSystemHandle对象;
  • getFileHandle:返回一个Promise对象,用于获取目录中的文件;
  • getDirectoryHandle:返回一个Promise对象,用于获取目录中的目录;
  • removeEntry:返回一个Promise对象,用于删除目录中的文件或目录;
  • resolve:返回一个Promise对象,用于获取目录中的文件或目录;


entrieskeysvalues这三个方法都是用来获取目录中的所有文件和目录的,它们返回的都是一个AsyncIterable对象,我们可以通过for await...of语法来遍历它。

const directoryHandle = await window.showDirectoryPicker();
for await (const [name, handle] of directoryHandle.entries()) {
    if (handle.kind === 'file') {
        console.log(name, 'file');
    } else {
        console.log(name, 'directory');
    }
}

我们可以通过handle.kind来判断当前的FileSystemHandle对象是文件还是目录。


而这里的getFileHandlegetDirectoryHandle就是用来获取目录中的文件和目录的,它们都返回一个Promise对象,我们可以通过await来获取它们。

const directoryHandle = await window.showDirectoryPicker();
for await (const [name, handle] of directoryHandle.entries()) {
    if (handle.kind === 'file') {
        const fileHandle = await directoryHandle.getFileHandle(name);
        console.log(fileHandle);
    } else {
        const directoryHandle = await directoryHandle.getDirectoryHandle(name);
        console.log(directoryHandle);
    }
}

这里大家可以自己尝试一下,我就不截图了。


操作文件


上面我们了解到了如何获取文件和目录,那么我们接下来就来看看如何操作文件和目录。


读取文件


读取文件做过文件上传的同学应该都很熟悉了,我们可以使用FileReader对象来读取文件。

const fileHandle = await window.showOpenFilePicker({
    excludeAcceptAllOption: false,
    types: [
        {
            description: 'Text files',
            accept: {
                'text/plain': ['.txt'],
            },
        },
    ],
});
const file = await fileHandle[0].getFile();
const reader = new FileReader();
reader.onload = () => {
    console.log(reader.result);
};
reader.readAsText(file);

这里我们在使用showOpenFilePicker方法时,我们通过types属性来限制文件的类型,这样用户就只能选择文本文件了。


showOpenFilePicker还有其他的属性,例如:


  • multiple:一个boolean值,默认为false,是否允许用户选择多个文件;
  • excludeAcceptAllOption:一个boolean值,默认为false,是否允许用户选择所有类型的文件(就是选择文件下拉的所有文件选项);
  • types:一个数组,用于限制用户选择的文件类型(就是选择文件的下拉选项);
  • description:一个字符串,用于描述文件类型(就是下拉选项的文字);
  • accept:一个对象,用于描述文件类型(就是控制选择文件的类型,例如image/*表示图片类型),具体可以参考:MIME types


写入文件


写入文件可以使用上面提到的FileSystemFileHandle对象的createWritable方法来创建一个FileSystemWritableFileStream对象,然后通过它来写入文件。

const fileHandle = await window.showSaveFilePicker({
    types: [
        {
            description: 'Text files',
            accept: {
                'text/plain': ['.txt'],
            },
        },
    ],
});
// 创建一个可写流
const writable = await fileHandle.createWritable();
// 写入数据
await writable.write('Hello World!');
// 关闭流
await writable.close();

这里我们使用showSaveFilePicker方法来创建一个文件,然后通过createWritable方法来创建一个可写流,然后通过write方法来写入数据,最后通过close方法来关闭流。


showSaveFilePicker也是文件选择器的一种,它和showOpenFilePicker的区别在于,

showSaveFilePicker是用来创建文件的,而showOpenFilePicker是用来选择文件的。


showSaveFilePicker返回的是新创建的文件的FileSystemFileHandle对象,而showOpenFilePicker返回的是选择的文件的FileSystemFileHandle对象。


注意:操作文件流时,一定要记得关闭流哟,否则会导致文件锁定,无法进行其他操作,做前端的同学可能对这一块并不熟悉,所以特此提醒一下。


操作目录


上面我们已经知道了如何操作文件了,那么接下来我们就来看看如何操作目录。


创建目录


创建目录可以使用FileSystemDirectoryHandle对象的getDirectoryHandle方法来创建一个目录。

const directoryHandle = await window.showDirectoryPicker();
const newDirectoryHandle = await directoryHandle.getDirectoryHandle('new-directory', {
    create: true,
});


getDirectoryHandle方法接收两个参数:


  • name:一个字符串,用于指定目录的名称;
  • options:一个对象,用于指定目录的选项(可选);


  • create:一个boolean值,默认为false,是否创建目录;


目前只有create一个选项,如果设置为true,则会创建一个目录,如果设置为false,则会获取一个目录。


如果目录不存在,且createfalse,则会报错。


删除目录


删除目录可以使用FileSystemDirectoryHandle对象的removeEntry方法来删除一个目录。

const directoryHandle = await window.showDirectoryPicker();
await directoryHandle.removeEntry('new-directory');

removeEntry方法接收一个参数,一个字符串,用于指定要删除的目录的名称。


兼容性


截止到现在,showDirectoryPickershowOpenFilePicker这两个方法在Chrome 86版本中已经可以正常使用了,但是在Firefox中还不支持。


下面是来自caniuse的兼容性数据:

image.png

虽然Firefox还不支持,但是在一些实验性的项目上我们可以使用这些API,指定用户使用Chrome浏览器来访问。


总结


本文主要介绍了File System Access API的基本使用,包括如何获取文件和目录,以及如何操作文件和目录。


同时因为有这个API有跨域的问题,所以这次就没办法给大家演示码上掘金的代码了,感兴趣的同学可以将我文中的代码动手尝试一下。


可以发现我这次讲解的并不是很详细,因为这个API还在实验阶段,所以我只是简单的介绍了一下,如果大家想要了解更多的话,可以参考下面的参考资料。


参考资料


目录
相关文章
|
2月前
|
JSON API 开发工具
【Azure 应用服务】调用Azure REST API来获取 App Service的访问限制信息(Access Restrictions)以及修改
【Azure 应用服务】调用Azure REST API来获取 App Service的访问限制信息(Access Restrictions)以及修改
|
3月前
|
文字识别 小程序 安全
印刷文字识别操作报错合集之微信小程序调用API时路径总是返回不对,该如何处理
在使用印刷文字识别(OCR)服务时,可能会遇到各种错误。例如:1.Java异常、2.配置文件错误、3.服务未开通、4.HTTP错误码、5.权限问题(403 Forbidden)、6.调用拒绝(Refused)、7.智能纠错问题、8.图片质量或格式问题,以下是一些常见错误及其可能的原因和解决方案的合集。
|
3月前
|
文字识别 前端开发 API
印刷文字识别操作报错合集之通过HTTPS连接到OCR服务的API时报错,该如何处理
在使用印刷文字识别(OCR)服务时,可能会遇到各种错误。例如:1.Java异常、2.配置文件错误、3.服务未开通、4.HTTP错误码、5.权限问题(403 Forbidden)、6.调用拒绝(Refused)、7.智能纠错问题、8.图片质量或格式问题,以下是一些常见错误及其可能的原因和解决方案的合集。
|
3月前
|
DataWorks 关系型数据库 MySQL
DataWorks操作报错合集之调用CreateQualityRule API时,BlockType参数为0,会报错:"blockType less than minimum",该怎么办
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
3月前
|
前端开发 JavaScript API
惊天揭秘!AJAX与Fetch API如何让你的前后端交互秒变‘神级操作’!
【7月更文挑战第15天】在Web开发中,AJAX和Fetch API革新了前后端交互,告别了表单提交带来的页面刷新。AJAX利用XMLHttpRequest实现部分页面更新,开启无刷新时代;Fetch API作为现代替代,以其简洁和Promise支持简化异步操作。从AJAX的先驱地位到Fetch API的进化,两者提升了Web应用的性能和用户体验,成为现代开发的必备技能。
43 2
|
3月前
|
搜索推荐 API UED
资源部署及场景API调用体验过程的引导与操作流畅性
资源部署及场景API调用体验过程的引导与操作流畅性
|
2月前
|
自然语言处理 API 数据处理
惊了!浏览器居然自带语音API和流处理API!
惊了!浏览器居然自带语音API和流处理API!
39 0
|
2月前
|
存储 移动开发 编解码
一文读懂Web Codecs API:浏览器背后的媒体魔术师
一文读懂Web Codecs API:浏览器背后的媒体魔术师
31 0
|
3月前
|
XML JSON 文字识别
印刷文字识别操作报错合集之API调用过程中报错469,是什么导致的
在使用印刷文字识别(OCR)服务时,可能会遇到各种错误。例如:1.Java异常、2.配置文件错误、3.服务未开通、4.HTTP错误码、5.权限问题(403 Forbidden)、6.调用拒绝(Refused)、7.智能纠错问题、8.图片质量或格式问题,以下是一些常见错误及其可能的原因和解决方案的合集。
|
4月前
|
运维 DataWorks 数据管理
DataWorks操作报错合集之调用RegisterLineageRelation api时报错,是什么原因?
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
37 2

热门文章

最新文章