[英]How FileReader.readAsText in HTML5 File API works?
I wrote the following code to check whether the uploaded file exists or not using HTML5 file API.我编写了以下代码来使用 HTML5 文件 API 检查上传的文件是否存在。
<input type="file" id="myfile"> <button type="button" onclick="addDoc()">Add Document</button> <p id="DisplayText"></p>
The following JavaScript code has been mapped to it is as follows:以下 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>*/
}
After browsing a file from local system I tried to delete the "browsed" document form the folder before clicking on addDoc()
.从本地系统浏览文件后,我尝试在单击
addDoc()
之前从文件夹中删除“浏览过的”文档。 After clicking the button I could still see Filereader.result
is not null and could display all the content.单击按钮后,我仍然可以看到
Filereader.result
不为空,并且可以显示所有内容。
Can someone explain on how the Filereader works?有人可以解释Filereader 的工作原理吗? Is it that the FileReader gets bound as soon as the file is browsed?
FileReader是否在浏览文件后立即绑定?
Also can we check whether the system Readonly Attribute with FileReader similar to Java File.canread()
?也可以用类似于Java
File.canread()
FileReader来检查系统的Readonly属性吗?
Could someone suggest on this?有人可以对此提出建议吗? I have IE11 to test the code.
我有 IE11 来测试代码。
FileReader
load
event sets the .result
value asynchronously. FileReader
load
事件异步设置.result
值。 To access the .result
use load
or loadend
event.要访问
.result
使用load
或loadend
事件。
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
returned by .files
call.当在
<input type="file">
Choose File
或Browse...
UI 中Choose File
,在本地文件系统中删除文件不应影响.files
调用返回的FileList
的File
对象。 See 2.9.2.见2.9.2。 Transferable objects , 6.7.3 The DataTransfer interface .
可传输对象, 6.7.3 DataTransfer 接口。
4. The Blob Interface and Binary Data
4. Blob 接口和二进制数据
Each
Blob
must have an internal snapshot state , which must be initially set to the state of the underlying storage, if any such underlying storage exists, and must be preserved throughstructured clone
.每个
Blob
必须有一个内部快照 state ,它必须最初设置为底层存储的状态(如果存在任何此类底层存储),并且必须通过structured clone
保存。 Further normative definition ofsnapshot state
can be found forFile
s.可以为
File
找到snapshot state
进一步规范定义。
2.9.8 Monkey patch for Blob and FileList objects
2.9.8 Blob 和 FileList 对象的 Monkey 补丁
This monkey patch will be removed in due course.
这个猴子补丁将在适当的时候删除。 See w3c/FileAPI issue 32 .
请参阅w3c/FileAPI 问题 32 。
Blob
objects arecloneable objects
.Blob
对象是可cloneable objects
。
Each
Blob
object's [[Clone
]] internal method, given targetRealm and ignoring memory, must run these steps:每个
Blob
对象的 [[Clone
]] 内部方法,给定 targetRealm 并忽略内存,必须运行以下步骤:If this is
closed
, then throw a"DataCloneError"
DOMException
.如果这是
closed
,则抛出一个"DataCloneError"
DOMException
。Return a new instance of this in targetRealm , corresponding to the same underlying data.
在targetRealm 中返回this 的一个新实例,对应于相同的底层数据。
FileList
objects are cloneable objects .FileList
对象是可克隆的对象。Each
FileList
object's[[Clone]]
internal method, given targetRealm and memory , must run these steps:每个
FileList
对象的[[Clone]]
内部方法,给定targetRealm和memory ,必须运行以下步骤:
Let output be a new
FileList
object in targetRealm .让output成为targetRealm 中的一个新
FileList
对象。For each file in this , add ?
对于图中的每个文件,添加?
[StructuredClone][15](_file, targetRealm, memory_)
to the end of the list ofFile
objects of output .[StructuredClone][15](_file, targetRealm, memory_)
到输出的File
对象列表的末尾。Return output .
返回输出。
At chrome, chromium if read-only permission is set for file at local filesystem and user selects file at <input type="file">
element, where FileReader
is used to read file, an error is thrown at FileReader
, generated from FileReader
progress
event.在 chrome 中,如果在本地文件系统中为文件设置了只读权限,并且用户在
<input type="file">
元素处选择文件,其中FileReader
用于读取文件,则会在FileReader
处引发错误,由FileReader
progress
生成事件。
If a Blob URL
is set to the same file object, the blob:
URL will not return the the read-only file at request to the Blob URL
.如果
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
;在 chrome 中,设置了
webkitdirectory
属性并选择具有只读权限的文件夹FileList
.length
of event.target.files
返回0
; event.target.files.webkitGetAsEntry()
is not called, "No file chosen"
is rendered at <input type="file">
shadowDOM
. event.target.files.webkitGetAsEntry()
未被调用,在<input type="file">
shadowDOM
处呈现"No file chosen"
未"No file chosen"
<input type="file">
。 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 displayed at drop
event.dataTransfer
.当文件夹放置在
<input type="file">
或放置droppable
属性的元素处时,只读文件夹的目录.name
和.path
显示在drop
event.dataTransfer
。
When user drops file or folder at <textarea>
element, where no drop
event is attached beforeunload
event is called and a prompr is displayed at UI当用户删除文件或文件夹在
<textarea>
元素,在没有drop
附着事件beforeunload
事件被称为和prompr在UI显示
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
and .path
of the parent folder are accessible at .then()
chained to event.target.getFilesAndDirectories()
.在火狐版本47.0b9与
allowdirs
属性被设置在<input type="file">
元素,其中用户点击"Choose folder.."
<input>
,该文件夹.name
和.path
的父文件夹是在可访问的.then()
链接到event.target.getFilesAndDirectories()
。 The files or folders contained within the selected folder are not returned when recursively iterating Directory
entries;递归迭代
Directory
条目时,不会返回所选文件夹中包含的文件或文件夹; an an empty string is returned.返回一个空字符串。
If user clicks "Choose file..."
<input>
and a folder is selected without read-only permission set, when the folder at file manager is clicked, the files in the folder are listed.如果用户单击
"Choose file..."
<input>
并且选择了一个没有设置只读权限的文件夹,则单击文件管理器中的文件夹时,将列出该文件夹中的文件。
Where a folder is selected where read-only permission is set an alert()
notification is rendered at UI displaying如果选择了设置只读权限的文件夹,则会在 UI 显示时呈现
alert()
通知
Could not read the contents of <directory name> Permission denied
*nix OS *nix 操作系统
When user drops folder at <textarea>
element, where no drop
event is attached, the full path to the folder at user filesystem file:
protocol is exposed.当用户在
<textarea>
元素放置文件夹时,没有drop
事件附加,用户文件系统file:
协议中file:
夹的完整路径被公开。 The paths to the files contained within the folder are not also set as .value
;文件夹中包含的文件的路径也没有设置为
.value
; eg,例如,
"file:///home/user/Documents/Document/"
When a file is dropped at <textarea>
element, where not drop
event is attached, the full path to the file at user filesystem is set as .value
of <textarea>
;当一个文件在丢弃
<textarea>
元素,其中不drop
被附加事件,在用户文件系统中的文件的完整路径被设定为.value
的<textarea>
; that is,也就是说,
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.txt"
If multiple files are selected and dropped at <textarea>
element, all of the full file paths are set as .value
of <textarea>
, delineated by new line character \\n
如果在
<textarea>
元素中选择并放置多个文件,则所有完整文件路径都设置为<textarea>
.value
,以换行符分隔\\n
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue1.txt" "file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue2.txt" ..
Where an XMLHttpRequest()
is made for the file path and error is logged at console
为文件路径创建
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
event handler is called如果被设置为
.src
一个的<img>
与元件.crossOrigin
设置为"anonymous"
的img
error
事件处理程序被调用
At call to window.open()
with full path set at first parameter在调用
window.open()
,在第一个参数中设置了完整路径
Error: Access to '"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.png"' from script denied
4.10.5.1.18. 4.10.5.1.18。 File Upload state (
type=file
) 文件上传状态(
type=file
)
For historical reasons, the
value
IDL attribute prefixes the file name with the string "C:\\fakepath\\
".由于历史原因,
value
IDL 属性在文件名前加上字符串“C:\\fakepath\\
”。 Some legacy user agents actually included the full path (which was a security vulnerability).一些旧的用户代理实际上包含了完整路径(这是一个安全漏洞)。 As a result of this, obtaining the file name from the
value
IDL attribute in a backwards-compatible way is non-trivial.因此,以向后兼容的方式从
value
IDL 属性中获取文件名并非易事。
4.10.5.4. 4.10.5.4. Common
<input>
element APIs 常见的
<input>
元素 API
filename
文件名
On getting, it must return the string "C:\\fakepath\\" followed by the name of the first file in the list of
selected files
, if any, or the empty string if the list is empty.获取时,它必须返回字符串 "C:\\fakepath\\" 后跟
selected files
列表中第一个文件的名称(如果有),或者如果列表为空,则返回空字符串。 On setting, if the new value is the empty string, it must empty the list ofselected files
;设置时,如果新值是空字符串,则必须清空
selected files
列表; otherwise, it must throw an "InvalidStateError
"DOMException
.否则,它必须抛出“
InvalidStateError
”DOMException
。NOTE: This "fakepath" requirement is a sad accident of history.
注意:这个“fakepath”要求是历史上的一个可悲的意外。 See the example in the File Upload state section for more information.
有关更多信息,请参阅文件上传状态部分中的示例。
NOTE: Since
path components
are not permitted in file names in the list ofselected files
, the "\\fakepath\\
" cannot be mistaken for a path component.注意:由于
selected files
列表中的文件名中不允许使用path components
因此不能将“\\fakepath\\
”误认为是路径组件。
4.10.5.1.18. 4.10.5.1.18。 File Upload state (
type=file
) 文件上传状态(
type=file
)
When an
<input>
element'stype
attribute is in theFile Upload
state, the rules in this section apply.当
<input>
元素的type
属性处于File Upload
状态时,本节中的规则适用。The
<input>
elementrepresents
a list ofselected files
, each file consisting of a file name, a file type, and a file body (the contents of the file).<input>
元素represents
selected files
的列表,每个文件由文件名、文件类型和文件正文(文件内容)组成。File names must not contain
path components
, even in the case that a user has selected an entire directory hierarchy or multiple files with the same name from different directories.文件名不得包含
path components
,即使在用户选择了整个目录层次结构或来自不同目录的多个同名文件的情况下。 Path components , for the purposes of theFile Upload
state, are those parts of file names that are separated by U+005C REVERSE SOLIDUS character () characters.出于
File Upload
状态的目的,路径组件是文件名中由 U+005C REVERSE SOLIDUS 字符 () 字符分隔的那些部分。
Bug report https://bugzilla.mozilla.org/show_bug.cgi?id=1311823错误报告https://bugzilla.mozilla.org/show_bug.cgi?id=1311823
Following comment by Neal Deakin at bug report遵循Neal Deakin在错误报告中的评论
I think the steps referred to are:
我认为提到的步骤是:
- Open data:text/html,
打开数据:文本/html,
- Drag a file from the desktop to the textarea
从桌面拖一个文件到textarea
I can reproduce this on Linux, but not on Windows or Mac.
我可以在 Linux 上重现这个,但不能在 Windows 或 Mac 上重现。
The hunch above is correct;
上面的预感是正确的; Linux is including the data as a url and plaintext as well.
Linux 也将数据作为 url 和纯文本包含在内。
dropped files at data:
prototcol data URI
at firefox, and chrome, chromium在
data:
删除文件data:
firefox 和 chrome、chrome 上的协议data URI
data:text/html,<textarea></textarea>
The full path name of file or folder set as .value
of <textarea>
.设置为
<textarea>
.value
的文件或文件夹的完整路径名。
Dropping file at data URI
having only textarea
element at chrome, chromium replaces the data URI
with dropped file path at address bar, and loads the dropped file at the same tab, replacing the data URI
with the content of the dropped file.在 chrome 上只有
textarea
元素的data URI
处删除文件,chrome 在地址栏用删除的文件路径替换data URI
,并在同一选项卡上加载删除的文件,用删除的文件的内容替换data URI
。
plnkr http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview plnkr http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview
html
, javascript
to reproduce issue described above html
, javascript
来重现上述问题
<!DOCTYPE html> <html> <head> <style> body { height: 400px; } textarea { width: 95%; height: inherit; } </style> <script> window.onload = function() { var button = document.querySelector("#myfile + button"); var input = document.getElementById("myfile"); var display = document.getElementById("DisplayText"); var text = null; function readFullPathToFileOnUserFileSystem(e) { var path = e.target.value; console.log(path); var w = window.open(path, "_blank"); var img = new Image; img.crossOrigin = "anonymous"; img.onload = function() { document.body.appendChild(this); } img.onerror = function(err) { console.log("img error", err.message) } img.src = path; var request = new XMLHttpRequest(); request.open("GET", path.trim(), true); request.onload = function() { console.log(this.responseText) } request.error = function(err) { console.log(err.message) } request.send(); } display.addEventListener("input", readFullPathToFileOnUserFileSystem); input.addEventListener("change", addDoc); input.addEventListener("progress", function(event) { console.log("progress", event) }); button.addEventListener("click", handleText) function addDoc(event) { var mozResult = []; function mozReadDirectories(entries, path) { console.log("dir", entries, path); return [].reduce.call(entries, function(promise, entry) { return promise.then(function() { console.log("entry", entry); return Promise.resolve(entry.getFilesAndDirectories() || entry) .then(function(dir) { console.log("dir getFilesAndDirectories", dir) return dir }) }) }, Promise.resolve()) .catch(function(err) { console.log(err, err.message) }) .then(function(items) { console.log("items", items); var dir = items.filter(function(folder) { return folder instanceof Directory }); var files = items.filter(function(file) { return file instanceof File }); if (files.length) { console.log("files:", files, path); mozResult = mozResult.concat.apply(mozResult, files); } if (dir.length) { console.log(dir, dir[0] instanceof Directory, dir[0]); return mozReadDirectories(dir, dir[0].path || path); } else { if (!dir.length) { return Promise.resolve(mozResult).then(function(complete) { return complete }) } } }) .catch(function(err) { console.log(err) }) }; console.log("files", event.target.files); if ("getFilesAndDirectories" in event.target) { return (event.type === "drop" ? event.dataTransfer : event.target) .getFilesAndDirectories() .then(function(dir) { if (dir[0] instanceof Directory) { console.log(dir) return mozReadDirectories(dir, dir[0].path || path) .then(function(complete) { console.log("complete:", complete); event.target.value = null; }); } else { if (dir[0] instanceof File && dir[0].size > 0) { return Promise.resolve(dir) .then(function(complete) { console.log("complete:", complete); }) } else { if (dir[0].size == 0) { throw new Error("could not process '" + dir[0].name + "' directory" + " at drop event at firefox, upload folders at 'Choose folder...' input"); } } } }).catch(function(err) { console.log(err) }) } var reader = new FileReader(); reader.onload = function(e) { text = reader.result; console.log("FileReader.result", text); button.removeAttribute("disabled"); } reader.onerror = function(err) { console.log(err, err.loaded, err.loaded === 0, file); button.removeAttribute("disabled"); } reader.onprogress = function(e) { console.log(e, e.lengthComputable, e.loaded, e.total); } reader.readAsArrayBuffer(file); } function handleText() { // do stuff with `text`: `reader.result` from `addDoc` display.textContent = text; button.setAttribute("disabled", "disabled"); // set `text` to `null` if not needed or referenced again text = null; } } </script> </head> <body> <input type="file" id="myfile" webkitdirectory directory allowdirs> <button type="button" disabled>Add Document</button> <br> <br> <textarea id="DisplayText"></textarea> </body> </html>
plnkr http://plnkr.co/edit/8Ovw3IlYKI8BYsLhzV88?p=preview plnkr http://plnkr.co/edit/8Ovw3IlYKI8BYsLhzV88?p=preview
You can use change
event attached to #myfile
element to handle file selection action by user.您可以使用附加到
#myfile
元素的change
事件来处理用户的文件选择操作。
Substitute <textarea>
element for <p>
element to display result of load
event from .readAsText()
call.将
<textarea>
元素替换为<p>
元素以显示来自.readAsText()
调用的load
事件的结果。
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
element to variable referencing previously set reader.result
.要显示
.result
的FileReader
在click
在button
元件,组可变text
到reader.result
内load
的事件FileReader
在click
事件在button
组.textContent
的#DisplayText
元件到可变参考先前集reader.result
。
<!DOCTYPE html> <html> <style> body { height: 400px; } textarea { width:95%; height: inherit; } </style> <head> <script> window.onload = function() { var button = document.querySelector("#myfile + button"); var input = document.getElementById("myfile"); var display = document.getElementById("DisplayText"); var text = null; input.addEventListener("change", addDoc); button.addEventListener("click", handleText) function addDoc(event) { var file = this.files[0] var reader = new FileReader(); reader.onload = function(e) { text = reader.result; button.removeAttribute("disabled"); } reader.onerror = function(err) { console.log(err, err.loaded , err.loaded === 0 , file); button.removeAttribute("disabled"); } reader.readAsText(event.target.files[0]); } function handleText() { // do stuff with `text`: `reader.result` from `addDoc` display.textContent = text; button.setAttribute("disabled", "disabled"); // set `text` to `null` if not needed or referenced again text = null; } } </script> </head> <body> <input type="file" id="myfile" accept="text/*"> <button type="button" disabled>Add Document</button><br><br> <textarea id="DisplayText"></textarea> </body> </html>
The FileReader object lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read. FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
File objects may be obtained from a FileList object returned as a result of a user selecting files using the element, from a drag and drop operation's DataTransfer object, or from the mozGetAsFile() API on an HTMLCanvasElement.文件对象可以从作为用户使用该元素选择文件的结果返回的 FileList 对象、从拖放操作的 DataTransfer 对象或从 HTMLCanvasElement 上的 mozGetAsFile() API 获得。
The readAsText method is used to read the contents of the specified Blob or File. readAsText方法用于读取指定 Blob 或 File 的内容。 When the read operation is complete, the readyState is changed to DONE, the loadend is triggered, and the result attribute contains the contents of the file as a text string.
当读操作完成时,readyState 变为 DONE,loadend 被触发,result 属性包含文件内容作为文本字符串。
Syntax语法
instanceOfFileReader.readAsText(blob[, encoding]);
Parameters参数
Blob斑点
The Blob or File from which to read.要从中读取的 Blob 或文件。
encoding Optional编码可选
A string specifying the encoding to use for the returned data.一个字符串,指定用于返回数据的编码。 By default, UTF-8 is assumed if this parameter is not specified.
默认情况下,如果未指定此参数,则假定为 UTF-8。
For the metadata about a file we can check the File object F
such that: F has a readability state of OPENED.对于有关文件的元数据,我们可以检查 File 对象
F
,以便: F 的可读性状态为 OPENED。 F refers to the bytes byte sequence. F 指的是 bytes 字节序列。
F.size
is set to the number of total bytes in bytes. F.size
设置为以字节为单位的总字节数。 F.name
is set to n. F.name
设置为 n。 F.type
is set to t. F.type
设置为 t。
Note: The type t of a File is considered a parsable MIME type if the ASCII-encoded string representing the File object's type, when converted to a byte sequence, does not return undefined for the parse MIME type algorithm [MIMESNIFF].
注意:如果表示 File 对象类型的 ASCII 编码字符串在转换为字节序列时不会为解析 MIME 类型算法 [MIMESNIFF] 返回 undefined,则文件的类型 t 被视为可解析 MIME 类型。
F.lastModified
is set to d. F.lastModified
设置为 d。
See more about browser compatibility and detailed document for FileReader , File and readAsText at MDN, also this W3C draft for FileApi在 MDN 上查看更多关于浏览器兼容性和FileReader 、 File和readAsText 的详细文档,以及FileApi 的这个W3C 草案
Use this instead:-改用这个:-
function loadFileAsText() { var fileToLoad = document.getElementById("fileToLoad").files[0]; var fileReader = new FileReader(); fileReader.onload = function(fileLoadedEvent) { var textFromFileLoaded = fileLoadedEvent.target.result; document.getElementById("inputTextToSave").innerText = textFromFileLoaded; }; fileReader.readAsText(fileToLoad, "UTF-8"); }
<p>Select a File to Load:</p> <input type="file" id="fileToLoad"><button onclick="loadFileAsText()">Load Selected File</button> <br> <br> <br> <p>Text file loaded:</p> <p id="inputTextToSave"></p>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.