Chrome 控制台使用手册专栏【七】Application Panel

1,218 阅读19分钟

Application Panel 主要用来查看检查、修改、调试Web应用程序清单、应用缓存、Web后台服务、页面Frame窗体对象。大部分开发主要用来查看应用会话缓存Cookie和SessionStorage、以及本地缓存LocalStorage。

Application Panel 主要分为五个内容部分,选中需要查看信息项, image.png

则中心区域展示对应信息 image.png

下文将按信息模块依次描述对应查看内容以及使用

Application

Manifest(渐进式Web应用程序相关)

渐进式Web应用程序

Manifest 配置添加到移动设备主屏幕的相关,如打开地址、图标、标题、打开方式等。传送门-配置字段

Manifest面板用于检查您的 Web 应用程序清单,预览清单配置,可以模拟 Add to Homescreen 事件(不符合安装条件才会显示)。

如果您希望用户能够将您的Web应用添加到他们的移动设备主屏幕,您需要一个 Web 应用清单。清单定义了应用程序在主屏幕上的显示方式、从主屏幕启动时引导用户的位置以及应用程序在启动时的外观。

预览清单

设置好Manifest清单后,您可以使用Application -> Manifest 窗格对其进行检查。

image.png

  • 要查看清单源,请单击App Manifest标签下方的链接(manifest.json在上面的屏幕截图中)。

image.png

  • Add to Homescreen 添加到主屏幕按钮以模拟添加到主屏幕事件。查看下一部分了解更多信息。

    如果您的网站符合添加到主屏幕的条件,Chrome 将不再显示添加到主屏幕的横幅。

  • IdentityPresentation部分仅以更加用户友好的方式显示清单源中的字段。

  • Icons部分显示您指定的每个尺寸图标。

image.png

模拟添加到主屏幕事件

仅当网站至少被访问两次(两次访问之间至少间隔五分钟)时,才能将 Web 应用程序添加到主屏幕。在开发或调试“添加到主屏幕”工作流程时,此标准可能会带来不便。App Manifest窗格上的Add to Homescreen按钮可让您随时模拟添加到主屏幕事件。

在应用程序打开时单击Add to Homescreen会提示 Chrome 显示“将此站点添加到您的书架”横幅,这是移动设备的“添加到主屏幕”横幅的桌面等效项。

image.png

Tips:在模拟添加到主屏幕事件时保持控制台抽屉打开。控制台会告诉您清单是否有任何问题,并记录有关“添加到主屏幕”生命周期的其他信息。

Add to Homescreen功能还不能模拟移动设备的工作流程。

Add to Home Screen 更改(Chrome 68)

如果您的网站符合添加到主屏幕的条件,Chrome 将不再显示添加到主屏幕的横幅。相反,您可以控制何时以及如何提示用户。

安装条件

要提示用户,请侦听beforeinstallprompt事件,然后保存该事件(event)并向您的应用添加按钮或其他 UI 元素(#install-button),以表明它可以安装。

let installPromptEvent;

window.addEventListener('beforeinstallprompt', (event) => {
  // Prevent Chrome <= 67 from automatically showing the prompt
  event.preventDefault();
  // Stash the event so it can be triggered later.
  installPromptEvent = event;
  // Update the install UI to notify the user app can be installed
  document.querySelector('#install-button').disabled = false;
});

当用户单击安装按钮(#install-button)时,调用已保存的beforeinstallprompt事件的prompt()方法,Chrome 然后显示添加到主屏幕对话框。

image.png

btnInstall.addEventListener('click', () => {
  // Update the install UI to remove the install button
  document.querySelector('#install-button').disabled = true;
  // Show the modal add to home screen dialog
  installPromptEvent.prompt();
  // Wait for the user to respond to the prompt
  installPromptEvent.userChoice.then(handleInstall);
});

image.png

Service Workers(渐进式Web应用程序相关)

Service Workers 是浏览器在后台运行的脚本,与网页分开。这些脚本使您能够访问不需要网页或用户交互的功能,例如推送通知、后台同步和离线体验等。

Service Workers 面板用于操作 Service Worker 相关的所有任务,例如取消注册或更新服务、模拟推送事件、离线或停止 Service Worker。

传送门-Service worker 简介

查看Service Workers

如果有注册navigator.serviceWorker.register() Service Worker,在 Application -> Service Workers 面板检查和调试

image.png

  • 如果在当前打开的页面上注册了 service worker,那么您将看到它列在此面板中。例如,在上面的屏幕截图中,为https://events.google.com/io2016/.
  • Offline 复选框:将DevTools 置于离线模式。这相当于Network面板中可用的离线模式,或命令行菜单Go offline中的选项。

image.png

image.png

  • Update on reload 复选框:强制 service worker 在每次页面加载时更新。
  • Bypass for network 复选框:绕过 service worker 并强制浏览器进入网络以获取请求的资源。
  • Update 按钮:执行指定的 service worker 一次性更新。
  • Push 按钮:模拟没有负载的推送通知(也称为tickle)。
  • Sync 按钮:模拟后台同步事件。
  • Unregister 按钮:取消注册指定的 service worker。查看清除存储,了解一种取消注册Service Worker并通过单击按钮清除存储和缓存的方法。
  • Source 行:service worker 是什么时候安装的。该链接是 service worker 的源文件的名称。单击该链接会将您转到 service worker 的来源。
  • Status 行:service worker的状态。这一行的数字(#1在上面的屏幕截图中)表示 service worker 更新了多少次。如果您启用Update on reload复选框,您会注意到每次页面加载时数字都会增加。在状态旁边,您会看到一个start按钮(如果service worker已停止)或一个stop按钮(如果service worker正在运行)。Service Worker 被设计为随时由浏览器停止和启动。点击stop显式停止您的service worker按钮可以模拟。
  • Clients 行:service worker的工作范围。当您启用Show All复选框时,将列出所有已注册的service worker,这时focus按钮起作用。如果您单击在不同选项卡中运行的service worker旁边的focus按钮,Chrome 会聚焦该选项卡。

如果 service worker 导致任何错误,则会出现一个名为Errors的新标签。

Service Worker Error

Service Worker Cache

查看 Cache -> Cache Storage

Storage

点击 Application - Storage 查看当前 源 使用的缓存概览

image.png

点击 Clear site data 删除Web使用storage,删除内容范围通过勾选进行控制

image.png

勾选 clear 范围

image.png

Storage

Cookie

主要用于管理用户会话、存储用户个性化偏好以及跟踪用户行为。本节如何使用 Chrome DevTools 查看、编辑和删除页面的 cookie。

查看Cookie

选择Storage模块,展开 Cookie,选中当前页面域名

image.png

主面板展示当前选中域名下的所有Cookie信息列表

image.png

右击Cookie域名列表,可快速清空域名下的所有Cookie image.png

点击列表中的Cookie,可快速查看Cookie值

image.png

点击表头按内容排序,支持表头尺寸拖拽修改以查看列内容

image.png

Cookies表包含以下字段:

  • Name。cookie 的名称。
  • Value。cookie 的值。
  • Domain。cookie 所属域名。传送门-Cookie域名关系
  • path。加载cookie的路径,标识指定了域名下(请求下)的哪些路径可以接受 Cookie。 在访问子路径时,会包含其父路径的Cookie,而在访问父路径时,不包含子路径的Cookie
  • Expires/Max-Age。cookie 的过期时间。对于Session cookie,此值始终为Session
  • Size。cookie 的大小,以字节为单位。
  • HttpOnly。如果为 true,则此字段指示 cookie 只能通过 HTTP 使用,并且不允许 JavaScript 修改。
  • Secure。如果为 true,则此字段表示 cookie 只能通过安全的 HTTPS 连接发送到服务器。
  • SameSite。包含strictlax。Cookie的实验属性。
  • SameParty。如果为 true,则该字段表示允许在所有祖先帧都属于同一First-Party Set的上下文中设置或发送 cookie 。
  • Priority。包含lowmedium(默认),或者high或使用已弃用的cookie Priority属性。

工具栏

image.png

点击 image.png 刷新Cookie列表,点击 image.png 清空Cookie列表,点击image.png删除选中的Cookie

输入Filter image.png过滤Cookie列表,只支持按名称过滤 cookie ,不支持按其他字段过滤。

右击Cookie列表的一条Cookie,可展开快捷菜单

image.png

  • Show Request with this Cookie 查看Network与之相关的请求
  • sort by 选择排序行

image.png

  • Header Options 重置表格列宽尺寸

image.png

  • Refresh 刷新当前Cookie信息
  • Edit [Field] 编辑当前Cookie[Field]
  • Delete 删除当前Cookie

编辑Cookie

NameValueDomainPath和Expires / Max-Age字段是可编辑的。双击字段进行编辑。

image.png

image.png

或者右击单元格,选择 Edit [Field]

image.png

删除Cookie

选中一行Cookie,点击image.png删除一个Cookie

image.png

或者右击一行Cookie,点击Delete删除一个Cookie

image.png

点击image.png删除所有Cookie

image.png

或者右击左侧Cookie域名列表,选中Clear清空域名下所有Cookie

image.png

Session Storage

Session Storage 存储的数据将保存在浏览器会话中。当页面被关闭时,存储在 sessionStorage 的数据会被清除。

查看Session Storage

选择Storage模块,展开 Session Storage,选中当前页面域名

image.png

主面板展示当前选中域名下的所有Session Storage信息列表,以键值对存在

image.png

Session Storage表包含以下字段:

  • Name。Session Storage 的名称。
  • Value。Session Storage 的值。

右击Session Storage域名列表,可快速清空域名下的所有Session Storage

image.png

点击表中一行数据可查看完整值(json字符串自动格式化展开)

image.png

列表工具栏,功能同Cookie列表一样,支持刷新、过滤、清空、删除

image.png

列表支持拖拽表头改变列宽,

通过右击列表,选择Header options -> Reset Column 恢复默认列宽

image.png

右击列表弹出菜单同Cookie列表,支持单个SessionStorage删除、修改单元格、刷新数据等

编辑Session Storage

双击Key 或者 Value 单元格,可以编辑对应单元格内容,回车或者双击其他空白保存

image.png

创建Session Storage

点击列表空白处,默认新增一行输入,关闭自动聚焦到Key对应单元格,回车或者双击其他空白保存

image.png

image.png

删除Session Storage

单击选中列表一行,点击工具栏image.png删除单个SessionStorage,

或者右击选中行,选择Delete删除

image.png

点击工具栏image.png清空所有,或者右击域名选择Clear

image.png

console 控制台使用sessionStorage

window只读的sessionStorage 属性允许直接操作会话缓存(SessionStorage),window可不写

查看当前域下所有sessionStorage

image.png

sessionStorage取值,直接通过字符串索引访问,或者通过.getItem(key)

image.png

创建sessionStorage,使用.setItem(key, value)进行创建,同时也可用于修改sessionStorage

image.png

image.png

删除单个sessionStorage,使用.removeItem(key)删除指定key值的sessionStorage

image.png

删除所有sessionStorage,使用.clear()删除所有

image.png

Local Storage

Local Storage 存储的数据将保存在浏览器会话中。数据可以长期保留,除非手动或者强制清空localStorage的数据才会被删除。

查看Local Storage

选择Storage模块,展开 Local Storage,选中当前页面域名

image.png

主面板展示当前选中域名下的所有Local Storage信息列表,以键值对存在

image.png

Local Storage表包含以下字段:

  • Name。Local Storage 的名称。
  • Value。Local Storage 的值。

右击Local Storage域名列表,可快速清空域名下的所有Local Storage

image.png

点击表中一行数据可查看完整值(json字符串自动格式化展开)

image.png

列表工具栏,功能同Cookie列表一样,支持刷新、过滤、清空、删除

image.png

列表支持拖拽表头改变列宽,

通过右击列表,选择Header options -> Reset Column 恢复默认列宽

image.png

右击列表弹出菜单同Cookie列表,支持单个LocalStorage删除修改单元格、刷新数据等

编辑Local Storage

双击Key 或者 Value 单元格,可以编辑对应单元格内容,回车或者双击其他空白保存

image.png

创建Local Storage

点击列表空白处,默认新增一行输入,关闭自动聚焦到Key对应单元格,回车或者双击其他空白保存

image.png

image.png

删除Local Storage

单击选中列表一行,点击工具栏image.png删除单个LocalStorage,

或者右击选中行,选择Delete删除

image.png

点击工具栏image.png清空所有,或者右击域名选择Clear

image.png

console 控制台使用localStorage

window只读的localStorage 属性允许直接操作本地缓存(LocalStorage),window可不写

查看当前域下所有localStorage

image.png

localStorage取值,直接通过字符串索引访问,或者通过.getItem(key)

image.png

创建localStorage,使用.setItem(key, value)进行创建,同时也可用于修改localStorage

image.png

image.png

删除单个localStorage,使用.removeItem(key)删除指定key值的localStorage

image.png

删除所有localStorage,使用.clear()删除所有

image.png

IndexedDB

IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法。IndexedDB 为生成 Web Application 提供了丰富的查询能力,使我们的应用在在线和离线时都可以正常工作。传送门-IndexedDB文档

传送门-IndexDB使用

查看IndexedDB

选择Storage模块,展开 IndexedDB,选中一个IndexDB源

image.png

the_name-https://juejin.cn表示一个数据库,the_name表示数据库名称,https://juejin.cn 表示可以访问该数据库的源

image.png

the_name 数据库包含一个customers对象存储

image.png

nameemail 是对象索引

选择一个DB数据库,面板展示数据库信息(源、名称、版本、对象存储数量),以及数据库操作(删除、刷新)

image.png

点击Delete database删除数据库

image.png

点击Refresh database刷新数据库

image.png

点击数据库下的对象存储(表),查看对应的键值对

image.png

  • Total entries是对象存储中键值对的总数。
  • Key generator value是下一个可用的键值。此字段仅在使用autoIncrement时显示。

点击Value单元格的值展开,显示完整的值,或者通过右击行,选择Expand/Collapse 展开收缩Value单元格

image.png

image.png

单击一个索引,可根据该索引的值对对象存储进行排序(字母顺序)。

image.png

工具栏支持刷新、过滤、清空、删除操作

image.png

刷新IndexedDB

右击IndexedDB展开数据选项,点击Refresh刷新数据库

image.png

或者 在数据库信息面板点击Refresh database按钮,刷新数据库

image.png

或者选择数据库中的对象存储后,点击工具栏image.png按钮刷新对象存储

image.png

右击对象存储的键值对,选择Refresh刷新键值对

image.png

编辑IndexDB

IndexedDB 键和值不能从Application Panel编辑。但是,由于 DevTools 可以访问页面上下文,因此您可以在 DevTools 中运行 JavaScript 代码来编辑 IndexedDB 数据(控制台修改)。

删除IndexedDB

右击对象存储,点击Clear清空对象存储所有键值对

image.png

或者在对象存储工具栏点击image.png清空对象存储所有键值对

image.png

选中一条键值对,点击image.png删除单条键值对

image.png

或者右击一条键值对,选择Delete删除该条键值对

image.png

打开Storage窗格,确保勾选IndexedDB复选框,单击Clear site data按钮清除站点所有数据。

image.png

console 控制台使用 IndexedDB

基于 window.indexedDB API

  • 新增IndexedDB数据库

声明一个创建IndexedDB请求

window.indexedDB.open(db_name:string, version:integer)

IndexedDB声明请求接收三种不同的 DOM 事件:success(声明成功)、error(声明失败) 和 onupgradeneeded(版本更新)

var db_name = 'the_name'
var db

var request = window.indexedDB.open(db_name, 1)

request.onerror = function(event) {
  // Do something with request.errorCode!
  alert("Database error: " + event.target.errorCode);
};

request.onsuccess = function(event) {
  // Do something with request.result!
  db = event.target.result
};

// 更新版本,用来创建或者删除对象存储仓库
request.onupgradeneeded = function(event) {
  // 保存 IDBDataBase 接口
  db = event.target.result;

  // 为该数据库创建一个对象存储仓库
  var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
  
 // 创建对象支持索引
 objectStore.createIndex('name', 'name', { unique: false });
 objectStore.createIndex('emial', 'emial', { unique: true });
};

  • 新增IndexedDB对象存储仓库

使用 db.createObjectStore(name:string, opt:obj) 创建一个对象存储仓库,需要在onupgradeneeded监听中实现,否则会报错提示

opt 支持:

  • keyPath:string :使用键路径,指定主键索引名称,键值唯一值
  • autoIncrement:boolean : 使用键生成器,默认该设置是不开启的,从1开始,默认加1

声明完对象存储仓库,使用 store.createIndex(name, key, opt:{unique:boolean}) 声明对象索引,通过unique指明键值是否唯一

// 该事件仅在较新的浏览器中实现了
request.onupgradeneeded = function(event) {
  // 保存 IDBDataBase 接口
  db = event.target.result;

  // 为该数据库创建一个对象存储仓库
  var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
  
 // 创建对象支持索引
 objectStore.createIndex('name', 'name', { unique: false });
 objectStore.createIndex('emial', 'emial', { unique: true });
};
};
  • 使用事务(transaction)添加键值对

需要使用事务(transaction)才能对IndexedDB的对象存储进行操作

使用 db.transaction(stores:array, mode:string) 声明一个事务

支持三种模式 mode:

  • 'readonly':对象仓库只读,默认
  • 'readwrite':对象仓库支持读写
  • 'versionchange':支持新建或删除对象仓库或索引

事务接收三种不同的 DOM 事件:errorabort 和 complete

使用 transaction.objectStore(stores:array)读取对象存储仓库,只能从创建事务时指定的对象仓库中取出一个对象仓库

// 我们的客户数据看起来像这样。
const customerData = [
  { ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
  { ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
];

// 声明一个事务
var transaction = db.transaction(["customers"], "readwrite");

// 在所有数据添加完毕后的处理
transaction.oncomplete = function(event) {
  alert("All done!");
};

transaction.onerror = function(event) {
  // 不要忘记错误处理!
};

// 获取对象存储仓库,执行添加
var objectStore = transaction.objectStore("customers");
customerData.forEach(function(customer) {
  var request = objectStore.add(customer);
  request.onsuccess = function(event) {
    // event.target.result === customer.ssn;
  };
});

  • 使用事务(transaction)获取键值对

使用 store.get(key) 获取指定主键值的对象

var request = db.transaction(["customers"], "readwrite")
                .objectStore("customers")
                .get("444-44-4444");
request.onsuccess = function(event) {
  // 读取成功!
  alert("Name for SSN 444-44-4444 is " + request.result.name);
};
  • 使用事务(transaction)编辑键值对

同添加,只要主键一样,则替换新值,或者删除后,重新添加

  • 使用事务(transaction)删除对象索引

使用 store.deleteIndex(keyPath) 删除指定主键值的对象

var request = db.transaction(["customers"], "versionchange")
                .objectStore("customers")
                .deleteIndex("email");
request.onsuccess = function(event) {
  // 删除成功!
};
  • 使用事务(transaction)删除键值对

使用 store.delete(key) 删除指定主键值的对象

var request = db.transaction(["customers"], "readwrite")
                .objectStore("customers")
                .delete("444-44-4444");
request.onsuccess = function(event) {
  // 删除成功!
};
  • 使用事务(transaction)删除所有键值对

使用 store.clear() 删除所有键值对

  • 获取对此仓库索引

使用 store.index(key) 返回根据指定索引值关联对象形式,数据同点击对象索引得到的表格一致

image.png

Web SQL

传送门-Web SQL in DevTools

传送门-What is Web SQL

Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs。Web SQL 数据库可以在最新版的 Safari, Chrome 和 Opera 浏览器中工作。

查看Web SQL

展开Application->Web SQL,如果,testDB为数据库,展开后显示LOGSStudents为数据表,选中数据表LOGS查看数据表内容。

image.png

点击image.png刷新选中数据表

image.png

输入数据表列名,进行过滤展示,多个列名英文逗号分隔

image.png

只展示 id 列表,若输入有误则展示所有列

image.png

右击数据表,可以根据选中列进行排序或者恢复默认列宽

image.png

编辑Web SQL

查看 Web SQL 表时,您无法编辑 Web SQL 数据。但是您可以从 Web SQL 控制台执行用于编辑或删除表的语句。

删除Web SQL

打开 Storage 面板,确认选中 Web SQL,点击 Clear site data,删除站点所有缓存数据,Web SQL 也会被全部删除

image.png

执行SQL语句

点击数据库(不是数据表),面板展示控制行命令输入 > ,输入SQL语句进行数据表操作

传送门-SQL 基础语法

image.png

console 控制台使用 IndexedDB

核心方法:

  • openDatabase:这个方法使用现有的数据库或者新建的数据库创建一个数据库对象。
  • transaction:这个方法让我们能够控制一个事务,以及基于这种情况执行提交或者回滚。
  • executeSql:这个方法用于执行实际的 SQL 查询。

创建DataBase

使用 .openDatabase(name, version, displayName, size, callback) 方法来打开已存在的数据库,如果数据库不存在,则会创建一个新的数据库,使用代码如下:

var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);

参数说明:

  • name 数据库名称
  • version 版本号
  • displayName 描述文本
  • size 数据库大小
  • callback 创建成功回调

执行事务

使用 db.transaction(callback(tx)) 打开一个事务,通过事务调用 tx.executeSql(sql) 执行数据库操作

// 创建数据库testDB,以及新增一张数据表LOGS
var db = openDatabase('testDB', '1.0', 'Test DB', 2 * 1024 * 1024);
db.transaction(function (tx) {
    tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
    tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "菜鸟教程")');
    // 添加数据
    tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');
});

Trust Tokens (Chrome 89)

传送门-Trust Tokens

传送门-Trust Token 实例

信任令牌 (Trust Token) 是一种新 API。利用此 API,网站可以将有限数量的信息从一个浏览上下文传送到另一个上下文(例如,跨站),这样,无需被动跟踪即可防止欺诈。

利用信任令牌,来源能够向信任的用户颁发加密令牌。用户浏览器会存储令牌。随后,浏览器可以在其他上下文中使用令牌来评估用户的真实性。

利用信任令牌 API 可以将用户在一个上下文中的信任传递到另一个上下文中,而无需识别用户或关联两个身份。

可在 Chrome DevTools NetworkApplication->Trust Tokens选项卡中检查令牌

Network 请求查看

image.png

Application->Trust Tokens查看

image.png

Cache

传送门-Cache

Cache Storage

Cache 接口为缓存的 Request / Response  对象对提供存储机制。

传送门-Cache

CacheStorage 接口表示 Cache 对象的存储。通过 CacheStorage.open(cacheName) 得到一个 cache 对象。可以通过 caches 属性访问 CacheStorage

// "caches" is a global read-only variable, which is an instance of CacheStorage,
caches.open(cacheName).then(function(cache) {
  // Do something with your cache
});

传送门-CacheStorage

Service Worker Cache

查看 Service Worker 使用 Cache API缓存的资源的只读列表。

image.png

Tips:第一次打开缓存并向其添加资源时,DevTools 可能不会检测到更改。重新加载页面,您应该会看到缓存。

var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
  '/',
  '/styles/main.css',
  '/script/main.js'
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

Back/forward cache (Chrome 98)

传送门-Back/forward cache

bfcache 是一种内存缓存(属于浏览器优化),用于在用户导航离开时存储页面(包括 JavaScript 堆)的完整快照。整个页面都在内存中,如果用户决定返回,浏览器可以快速轻松地恢复它。

导航到要测试的特定页面,然后在 DevTools 中转到Application->Back-forward Cache。接下来,单击Test back/forward cache按钮,DevTools 将尝试导航并返回以确定页面是否可以从 bfcache 恢复。

image.png

Background Services

Frames

点击Frames下的一个窗口对象,可以查看窗口对象的详细信息

image.png

展开窗体作用域类型,查看作用域文件

image.png

点击文件可查看文件内容

image.png