HTML5 文件 API 中的 FileReader.readAsText 如何工作?

新手上路,请多包涵

我编写了以下代码来使用 HTML5 文件 API 检查上传的文件是否存在。

 <input type="file" id="myfile">
<button type="button" onclick="addDoc()">Add Document</button>
<p id="DisplayText"></p>

以下 JavaScript 代码已映射到它,如下所示:

 function addDoc() {
  var file=document.getElementById("myFile").files[0]; //for input type=file
  var reader=new FileReader();
  reader.onload = function(e) {}
  reader.readAsText(file);
  var error = reader.error;
  var texte=reader.result;
  document.getElementById("DisplayText").innerText=reader.result; /*<p id="DisplayText>*/
}

从本地系统浏览文件后,我尝试在单击 addDoc() 之前从文件夹中删除“已浏览”文档。单击按钮后我仍然可以看到 Filereader.result 不为空并且可以显示所有内容。

有人可以解释 Filereader 是如何工作的吗?文件浏览器是否在浏览文件后 立即 绑定?

也可以看看系统的 Readonly Attribute是否有类似于Java的 FileReader File.canread()

有人可以对此提出建议吗?我有 IE11 来测试代码。

原文由 sushmithaP 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 427
1 个回答

FileReader load 事件异步设置 .result 值。要访问 .result 使用 loadloadend 事件。

When a file has been selected at <input type="file"> Choose File or Browse... UI, deleting file at local filesystem should not effect the File object at FileList.files 调用返回。见 2.9.2。可传输对象6.7.3 DataTransfer 接口

4. Blob接口和二进制数据

每个 Blob 必须有一个内部 _快照状态_,它必须最初设置为底层存储的状态,如果存在任何这样的底层存储,并且必须通过 structured clone 保存。 snapshot state 的进一步规范定义可参见 File s。

2.9.8 Blob 和 FileList 对象的 Monkey 补丁

这个猴子补丁将在适当的时候被删除。请参阅 w3c/FileAPI 问题 32

Blob 对象是 cloneable objects

  1. 每个 Blob 对象的 [[ Clone ]] 内部方法,给定 targetRealm 并忽略内存,必须运行以下步骤:

  2. 如果这是 closed ,则抛出 "DataCloneError" DOMException

targetRealm 中返回 this 的一个新实例,对应于相同的底层数据。

FileList 对象是可克隆的 对象

每个 FileList 对象的 [[Clone]] 内部方法,给定 targetRealmmemory ,必须运行这些步骤:

  1. 输出 成为 targetRealm 中的新对象 — FileList 对象。

  2. 对于其中的每个 _文件_,添加 ? [StructuredClone][15](_file, targetRealm, memory_)File 输出 对象列表的末尾。

返回 _输出_。


在 webkit 和 firefox 浏览器中选择只读文件或文件夹

在 chrome 中,如果在本地文件系统中为文件设置了只读权限并且用户在 <input type="file"> 元素中选择文件,其中 FileReader 用于读取文件,则会抛出错误 FileReader ,从 FileReader progress 事件生成。

如果 Blob URL 设置为相同的文件对象,则 blob: URL 将不会在请求时返回只读文件 Blob URL

选择文件夹权限设置为只读的文件夹

铬,铬

At chrome, chromium where webkitdirectory attribute is set and folder is selected with read-only permission FileList .length of event.target.files returned 0 ; event.target.files.webkitGetAsEntry() 不被调用, "No file chosen"<input type="file"> shadowDOM When a folder is dropped at <input type="file"> or element where droppable attribute set, the directory .name and .path of the read-only folder is显示在 drop event.dataTransfer

当用户将文件或文件夹放在 <textarea> 元素时,其中没有 drop 附加事件 beforeunload 在 UI prompr 上显示事件并调用

> Do you want to leave this site?
> Changes you made may not be saved.
> <Stay><Leave> // <buttons>
>
> ```

### 火狐

At firefox version 47.0b9 with `allowdirs` attribute is set at `<input type="file">` element, where user clicks `"Choose folder.."` `<input>` , the folder `.name` 父文件夹的 `---` 和 `.path` 可在 `.then()` 链接到 `event.target.getFilesAndDirectories()` 访问。递归迭代时不返回所选文件夹中包含的文件或文件夹 `Directory` 条目;返回一个空字符串。

如果用户点击 `"Choose file..."` `<input>` 并且选择了一个没有设置只读权限的文件夹,当点击文件管理器中的文件夹时,会列出该文件夹中的文件。

在选择了只读权限设置的文件夹的地方 `alert()` 在 UI 显示时呈现通知

> ```
>   Could not read the contents of <directory name>
>   Permission denied
>
> ```

# **错误,安全问题**

\*尼克斯操作系统

当用户将文件夹放置在 `<textarea>` 元素,其中没有附加 `drop` 事件时,用户文件系统文件夹的完整路径 `file:` 暴露。文件夹中包含的文件的路径也未设置为 `.value` ;例如,

“file:///home/user/Documents/Document/”


当文件被放置在 `<textarea>` 元素,而不是 `drop` 附加事件时,用户文件系统中文件的完整路径被设置为 `.value` `<textarea>` b5ad0 `---` ;那是,

“file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.txt”


如果选择多个文件并将其拖放到 `<textarea>` 元素,则所有完整文件路径都设置为 `.value` 的 `<textarea>` `\n`

“file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue1.txt” “file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue2.txt” ..


其中 `XMLHttpRequest()` 为文件路径创建,错误记录在 `console`

NS_ERROR_DOM_BAD_URI: Access to restricted URI denied


When set as `.src` of an `<img>` element with `.crossOrigin` set to `"anonymous"` the `img` `error` 事件处理器被调用

在调用 `window.open()` 时在第一个参数中设置了完整路径

Error: Access to ‘“file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.png”’ from script denied


## 规格

[4.10.5.1.18。文件上传状态( `type=file` )](https://w3c.github.io/html/sec-forms.html#file-upload-state-typefile)

> [例 16](https://w3c.github.io/html/sec-forms.html#example-8eea6b94)
>
> 由于历史原因, [`value`](https://w3c.github.io/html/sec-forms.html#dom-htmlinputelement-value) IDL 属性在文件名前加上字符串“ `C:\fakepath\` ”作为前缀。一些遗留用户代理实际上包括完整路径(这是一个安全漏洞)。因此,以向后兼容的方式从 `value` IDL 属性获取文件名并非易事。

[4.10.5.4。通用 `<input>` 元素API](https://w3c.github.io/html/sec-forms.html#common-input-element-apis)

> _**文件名**_
>
> 获取时,它必须返回字符串“C:\\fakepath\\”,后跟 [`selected\
> files`](https://w3c.github.io/html/sec-forms.html#selected-files) 列表中的第一个文件的名称(如果有),如果列表为空,则返回空字符串。在设置时,如果新值是空字符串,它必须清空 `selected files` 的列表;否则,它必须抛出一个“ `InvalidStateError` ” `DOMException` 。
>
> > **注意:** 这个“fakepath”要求是历史上的一个不幸事故。有关详细信息,请参阅 [文件上传](https://w3c.github.io/html/sec-forms.html#element-statedef-input-file-upload) 状态部分中的示例。
> >
> > **注意:** 由于 `path components` 不允许出现在 `selected files` 列表中的文件名中,因此不能将“ `\fakepath\` ”路径误认为组件。

[4.10.5.1.18。文件上传状态( `type=file` )](https://w3c.github.io/html/sec-forms.html#file-upload-state-typefile)

## **路径组件**

> 当 `<input>` 元素的 `type` 属性处于 `File Upload` 状态时,适用本节中的规则。
>
> `<input>` 元素 \-\-\- \-\-\- `selected files` [`represents`](https://w3c.github.io/html/dom.html#represent) 的列表,每个文件由文件名、文件类型和文件主体组成)(内容.
>
> 文件名不得包含 [`path components`](https://w3c.github.io/html/sec-forms.html#path-components) ,即使用户选择了整个目录层次结构或来自不同目录的多个同名文件。就 `File Upload` 状态而言, **路径组件** 是由 U+005C REVERSE SOLIDUS 字符 () 字符分隔的文件名部分。

错误报告 [https://bugzilla.mozilla.org/show_bug.cgi?id=1311823](https://bugzilla.mozilla.org/show_bug.cgi?id=1311823)

* * *

### 将文件拖放到数据 URI 的 <textarea>

根据 [Neal Deakin](https://bugzilla.mozilla.org/show_bug.cgi?id=1311823#c13) 在错误报告中的评论

> 我认为提到的步骤是:
>
> 1. 开放数据:文本/html,
> 2. 将文件从桌面拖到文本区域
>
> 我可以在 Linux 上重现它,但不能在 Windows 或 Mac 上重现。
>
> 上面的预感是正确的; Linux 也将数据作为 url 和明文包含在内。

在 `data:` 协议 `data URI` 在 firefox 和 chrome, chromium 删除文件

data:text/html,


### 火狐

文件或文件夹的完整路径名设置为 `.value` 的 `<textarea>` 。

### 铬,铬

将文件拖放到 `data URI` 只有 `textarea` chrome 的元素,chrome 将 `data URI` 替换为地址栏中相同选项卡的拖放文件路径,并加载,将 `data URI` 替换为拖放文件的内容。

plnkr [http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview](http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview)

* * *

`html` , `javascript` 重现上述问题

<!DOCTYPE html>




plnkr [http://plnkr.co/edit/8Ovw3IlYKI8BYsLhzV88?p=preview](http://plnkr.co/edit/8Ovw3IlYKI8BYsLhzV88?p=preview)

* * *

您可以使用 `change` 附加到 `#myfile` 元素的事件来处理用户的文件选择操作。

Substitute `<textarea>` element for `<p>` element to display result of `load` event from `.readAsText()` call.

To display `.result` of `FileReader` at `click` at `button` element, set variable `text` to `reader.result` within `load` event of `FileReader` at `click` event at `button` set `.textContent` of `#DisplayText` 元素到先前设置的变量引用 `reader.result` 。

<!DOCTYPE html>



“`

原文由 guest271314 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题