Web 应用程序的文件系统写入能力

news2024/12/22 23:10:15

介绍

NodeJS 之前,JS 操作文件只能通过 HTML <input type="file"> 元素或 XMLHttpRequest(或之后的 fetch),来对本地文件进行一些浏览和上传操作。NodeJS 给予了 JS 操作系统底层 API 的能力,但这只能局限在 NodeJS 项目中。

File System Access API 允许直接读取、写入或保存对用户设备上的文件和文件夹的更改。此 API 使开发人员能够构建功能强大的 Web 应用程序,例如 IDE、文本编辑器、图片编辑器和视频编辑器等等。

从 Chrome 86 开始支持 File System Access API,目前只有基于 Chromium 系列的浏览器全面支持,Safari 部分支持(支持读取,不支持写入和保存),而 Firefox 未支持。

下面我们从制作一个网页文本编辑器,来演示文件系统访问 API。

读取文件

大多数与文件和目录的交互都是通过句柄(FileSystemHandle 的子类)完成的。获取句柄的方法通常是 window.showOpenFilePicker 和 window.showDirectoryPicker,调用必须在安全上下文中完成,并且必须从用户手势(事件触发)中调用。

let fileHandle;
butOpenFile.addEventListener('click', async () => {[fileHandle] = await window.showOpenFilePicker();
}); 

保留对文件句柄的引用很有帮助,以便以后可以使用。例如,需要它来保存对文件的更改,或执行任何其他文件操作。

获取了文件的句柄,您可以获取文件的属性,或访问文件本身。调用 handle.getFile() 将返回一个 File 对象,然后我们可以通过 slice(), stream(), text(), 或 arrayBuffer() 等方法对其处理。

const file = await fileHandle.getFile();
const contents = await file.text(); 

注意:FileSystemFileHandle.getFile() 返回的 File 对象只有在磁盘上的文件未更改时才可读。如果磁盘上的文件被修改,File 对象将变得不可读,您将需要再次调用 getFile() 以获取新的 File 对象来读取更改后的数据。

下面当点击按钮时,浏览器会显示一个文件选择器。一旦他们选择了一个文件,应用程序就会读取内容并将它们放入一个 <textarea> 内显示。

let fileHandle;
butOpenFile.addEventListener('click', async () => {[fileHandle] = await window.showOpenFilePicker();const file = await fileHandle.getFile();const contents = await file.text();textArea.value = contents;
}); 

写入文件

将数据写入磁盘需要使用一个 FileSystemWritableFileStream 对象,通过文件句柄对象调用 fileHandle.createWritable() 来创建该可写流。

FileSystemWritableFileStream.write(data)

在当前文件光标偏移处将内容写入调用该方法的文件中。

参数 data 可以为以下类型:ArrayBuffer、TypedArray、DataView、Blob、String 类型或包含以下属性的对象:

  • type为以下之一的字符串:“write”、“seek” 或 “truncate”。
  • data要写入的文件数据,可以为以下类型:ArrayBuffer、TypedArray、DataView、Blob。如果 type 设置为 “write”,则此属性是必需的。
  • position如果 type 设置为 “seek”,表示当前文件光标应移动到的字节位置。如果 type 设置为 “write”,表示开始写入的位置。
  • size一个无符号 long 类型,表示流应包含的字节数。如果 type 设置为 “truncate”,则此属性是必需的。

该方法返回一个包含 undefined 的 Promise。

// 只传入数据
writableStream.write(data);
// 从确定的位置将数据写入流
writableStream.write({ type: "write", position, data });
// 将当前文件光标偏移量更新到指定位置
writableStream.write({ type: "seek", position });
// 将文件大小调整为 size 字节长
writableStream.write({ type: "truncate", size }); 

要注意的是,在流关闭之后,才会将更改写入磁盘上的实际文件。

async function writeFile(fileHandle, contents) {const writable = await fileHandle.createWritable();await writable.write(contents);await writable.close();
} 

另外,还可以将流直接通过管道传递给写入流,下面 pipeTo() 方法调用后,默认关闭目标管道,无需再关闭写入流。

async function writeURLToFile(fileHandle, url) {const writable = await fileHandle.createWritable();const response = await fetch(url);await response.body.pipeTo(writable);
} 

showSaveFilePicker(options)

显示一个允许用户保存文件的文件选择器。返回处理后的包含 FileSystemFileHandle 对象的 Promise。

参数 options 可选,支持以下属性:

  • id通过指定一个 id,浏览器可以记住上次使用的目录。
  • startIn起始目录,例如 “desktop”(桌面), “documents”(文档), “downloads”(下载), “music”(音乐), “pictures”(图片), “videos”(视频)。还可以将现有文件或目录句柄传递到此参数。
  • suggestedName文件名。
  • excludeAcceptAllOption默认为 false,是否排除 types 中的 accept 文件类型列表。
  • types可选择的文件类型数组,每个数组项也是个对象,支持下面两个参数:* description文件或者文件夹的描述,字符串,可选。* accept一个对象,键为 MIME 类型,值为保存的扩展名数组。

如果需要保存为一个 .txt 扩展名的文本文件:

async function getNewFileHandle() {const opts = {types: [{description: 'Text file',accept: {'text/plain': ['.txt']},}],};return await window.showSaveFilePicker(opts);
} 

一般在文本编辑器中,有两种保存文件的方法:保存和另存为。保存只是使用先前检索到的文件句柄将更改写回原始文件。但是另存为会创建一个新文件,因此需要一个新的文件句柄。

注意事项

1.需要 https 协议,如果是本地 localhost 不受此限制。
2.不能在 iframe 内使用,会报 SecurityError。所以很遗憾,马上掘金上面不能体验了。

Uncaught (in promise) {"name":"SecurityError","message":"Failed to execute 'showSaveFilePicker' on 'Window': Cross origin sub frames aren't allowed to show a file picker.","stack":"Error: Failed to execute 'showSaveFilePicker' on 'Window': Cross origin sub frames aren't allowed to show a file picker.\n at HTMLButtonElement. (:17:37)"} 

使用

下面定义两个按钮,分别写入文本和图片并保存。文本和图片 URL 可以根据需求自定义。

<body><button id="saveText">保存文本文件</button><button id="saveImg">保存图片</button>
</body>
<script> async function writeFile(fileHandle, contents) {const writable = await fileHandle.createWritable();await writable.write(contents);await writable.close();}async function writeURLToFile(fileHandle, url) {const writable = await fileHandle.createWritable();const response = await fetch(url);await response.body.pipeTo(writable);}saveText.addEventListener('click', async function() {const opts = {startIn: 'downloads',types: [{description: 'Text file',accept: { 'text/plain': ['.txt'] },}],suggestedName: 'Untitled',id: 0,};await writeFile(await window.showSaveFilePicker(opts), '你好!');});saveImg.addEventListener('click', async function() {const opts = {startIn: 'downloads',types: [{description: 'Image file',accept: { 'image/jpg': ['.jpg'] },}],suggestedName: 'Untitled',id: 0,};await writeURLToFile(await window.showSaveFilePicker(opts),'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/211a1a5980f94f0095a46017e9bc9755~tplv-k3u1fbpfcp-watermark.image?');}); </script>
<style> button {border: 0;border-radius: .5em;padding: 1em;background: coral;color: white;} </style> 

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

章节7 查看和处理文件内容

7-查看和处理文件内容 文本文件 ASCII、UTF-8、Unicode、ANSItxt、xml、conf、properties、yml等配置文件、日志文件、源代码 二进制文件 可执行文件、图片、音频、视频 cat 全拼&#xff1a;concatenate [kənˈkt(ə)nˌeɪt] 连接 格式&#xff1a;cat 文件名 more/…

eyeurl—一款网页批量截图工具

eyeurl使用说明 开发说明 eyeurl由作者&#xff1a;云小书 开发&#xff0c;源于日常渗透测试中&#xff0c;信息收集到的url过多&#xff0c;挨个打开查看比较繁琐&#xff0c;且效率极低&#xff0c;网上有大佬开发的eyewitness&#xff0c;且ui布局各方面都比较完善&#…

sadserver 题目思路概述

背景 从 阮一峰老师的博客 了解到 sadserver 可以在线挑战一些 linux 指令相关问题&#xff08;整体难度一般&#xff0c;但做题体验不错&#xff0c;有提示&#xff09;&#xff0c;这里将目前网站提供的的16道题进行简单解答&#xff0c;提供思路和相关指令 本文csdn 博客地…

初识Java虚拟机

1.概述 Java虚拟机&#xff1a;Java Virtual Machine。正是有了Java虚拟机&#xff0c;Java语言实现了跨平台的特性&#xff0c;一次编译&#xff0c;多处运行。 目前使用范围最广的虚拟机就是Hotspot VM&#xff0c;它是OracleJDK和OpenJDK中的默认Java虚拟机。 相比于其他…

[Android Studio]开发APP应用出现软件程序打开闪退的排错

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f4cb;笔记目…

你还没用过Mybatis-Plus?丝般顺滑,快速上手!

一、概述 1.1、什么是MyBatis-Plus MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window)的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 1.2、特性 无侵入&#xff1a;只做…

RabbitMQ入门前篇

本篇博文目录:一.RabbitMQ1.消息队列2.RabbitMQ3.安装RabbitMQ4.RabbitMQ常用命令二.使用RabbitMQ进行编程1.AMQP2.第一次MQ通信三.RabbitMQ六中工作模式1.RabbitMQ2.Work queues3.pub/sub订阅发布模式4.Routing模式5.主题Topic模式四.RabbitMQ消息确认机制五.源代码下载一.Rab…

我性格比较内向,适合做管理吗?

许多刚走上管理岗位的朋友&#xff0c;都有这样的困惑&#xff1a;1.我比较内向&#xff0c;不适合做管理。2.我不擅长演讲&#xff0c;没有领导才能。3.我太谨小慎微了&#xff0c;做不好领导。4.我太喜欢出风头&#xff0c;静不下心来做管理。5.我太强势了&#xff0c;团队很…

GuLi商城-项目初始结构创建,GitHub仓库创建

GitHub账号和密码 账号&#xff1a;11360XXXXXqq.com 密码&#xff1a;ZH**SH*19**1016 新建仓库&#xff1a; gulimall 记得勾选下Add a README file&#xff0c;上面忘记勾选了&#xff0c;实际建议还是要勾选下 复制路径&#xff1a; 打开IDEA检出项目 创建商品微服务模…

芯片设计|FPGA 设计的指导原则(一)

这一部分主要介绍 FPGA/CPLD 设计的指导性原则&#xff0c;如 FPGA 设计的基本原则、基本设计思想、基本操作技巧、常用模等。 FPGA/CPLD 设计的基本原则、思想、技巧和常用模块是一个非常大的问题&#xff0c;在此不可能面面俱到&#xff0c;只能我们公司项目中常用的一些设计…

权值线段树 详解+操作模板(c++)

文章目录权值线段树添加一个数字求某数出现的次数查询一段区间中数字出现的次数查询整个值域中第k小的数查询整个值域中第k大的数例子&#xff1a;求逆序对关于基本线段树与线段树的模板&#xff0c;请看我们之前发布的博客&#xff1a; 线段树入门详解 维护加法乘法&#xff0…

关于“茴香豆的‘茴’有几种写法”:学习过程中,若时间精力有限则优先记住最好用的一种

学习过程中的细节整理和精力节省权衡 我平时学习有整理总结、记笔记的习惯。 我学新东西总是很慢&#xff0c;因为细节处几乎都不会放过&#xff0c;会去发散&#xff0c;去深挖&#xff0c;去比较之前。 刚才上网&#xff0c;查了C语言中二维数组的赋值方式&#xff0c;某个…

UVM实战笔记(七)

第七章. UVM中的寄存器模型 7.1 寄存器模型简介 7.1.1 带寄存器配置总线的DUT 本章节使用的DUT带寄存器配置&#xff0c;代码如下&#xff1a; module dut(clk,rst_n,bus_cmd_valid,bus_op,bus_addr,bus_wr_data,bus_rd_data,rxd,rx_dv,txd,tx_en)input clk; …

DaVinci:Camera Raw(Sony RAW)

本文主要介绍 Sony RAW 格式素材相关的 Camera Raw 参数。解码质量Decode Quality解码质量决定了图像解拜耳之后所呈现的素质。默认为“使用项目设置” Use project setting&#xff0c;表示使用项目设置对话框中的“Camera RAW”解码质量设置。还可选择&#xff1a;全分辨率 -…

JavaEE-网络编程

目录一、网络编程套接字二、UDP Socket2.1 客户端服务器程序-回显服务(EchoServer)2.1.1 UdpEchoServer2.1.2 UdpEchoClient2.1.3 一个简单程序三、TCP 客户端服务器程序3.1 TCP API一、网络编程套接字 网络编程套接字就是操作系统给应用程序提供的一组API(叫做socket API)。 …

NLP学习笔记(七) BERT简明介绍

大家好&#xff0c;我是半虹&#xff0c;这篇文章来讲 BERT\text{BERT}BERT (Bidirectional Encoder Representations from Transformers) 原始论文请戳这里 0 概述 从某种程度上来说&#xff0c;深度学习至关重要的一环就是表征学习&#xff0c;也就是学习如何得到数据的向…

怎么把两个PDF合并?教你们几个简单的方法

不知道大家平时处理文件的数量多不多&#xff0c;但是小编日常处理文件真的特别多&#xff0c;所以小编经常会使用专业的格式转换器来处理文件&#xff0c;这样就可以高效处理文件了&#xff0c;例如我们需要将多个PDF文件合并&#xff0c;这样就只需要传输一个文件就可以了&am…

自定义starter解决请求绕过网关问题

引言 微服务项目中网关是一个常见的模块&#xff0c;通过网关的分发可以实现负载均衡、鉴权等操作&#xff1b;但是搭建好网关可以发现&#xff0c;虽然可以通过网关端口请求后端&#xff0c;如果有其他服务的地址依然可以使用其他服务地址绕过网关请求&#xff0c;这里我提供…

利用RadminLan和TcpRoute2将工作带回家

需要准备的工具 1.RadminLan 下载地址–>https://www.radmin-lan.cn/ 2.TcpRoute2 项目地址–>https://github.com/GameXG/TcpRoute2 *选用&#xff1a;浏览器插件proxy-switchyomega&#xff1a;https://microsoftedge.microsoft.com/addons/detail/proxy-switchyomega…

Visual Studio Code 的安装和使用

Visual Stuio Code 微软出的一款免费编辑器。 有 Windows、Linux 和macOS 三种版本的&#xff0c;属于跨平台的编辑器。它功能强大&#xff0c;支持插件工具安装&#xff0c;对于写代码、阅读代码的人来说是非常方便的。 1、安装 Visual Stuio Code 下载地址如下&#xff1a; h…