![](/img/trans.png)
[英]FileReader Error from “How FIleReader.readAsText in HTML5 File API works”
[英]How FileReader.readAsText in HTML5 File API works?
我编写了以下代码来使用 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 的工作原理吗? FileReader是否在浏览文件后立即绑定?
也可以用类似于Java File.canread()
FileReader来检查系统的Readonly属性吗?
有人可以对此提出建议吗? 我有 IE11 来测试代码。
FileReader
load
事件异步设置.result
值。 要访问.result
使用load
或loadend
事件。
当在<input type="file">
Choose File
或Browse...
UI 中Choose File
,在本地文件系统中删除文件不应影响.files
调用返回的FileList
的File
对象。 见2.9.2。 可传输对象, 6.7.3 DataTransfer 接口。
每个
Blob
必须有一个内部快照 state ,它必须最初设置为底层存储的状态(如果存在任何此类底层存储),并且必须通过structured clone
保存。 可以为File
找到snapshot state
进一步规范定义。
2.9.8 Blob 和 FileList 对象的 Monkey 补丁
这个猴子补丁将在适当的时候删除。 请参阅w3c/FileAPI 问题 32 。
Blob
对象是可cloneable objects
。
每个
Blob
对象的 [[Clone
]] 内部方法,给定 targetRealm 并忽略内存,必须运行以下步骤:如果这是
closed
,则抛出一个"DataCloneError"
DOMException
。在targetRealm 中返回this 的一个新实例,对应于相同的底层数据。
每个
FileList
对象的[[Clone]]
内部方法,给定targetRealm和memory ,必须运行以下步骤:
让output成为targetRealm 中的一个新
FileList
对象。对于图中的每个文件,添加?
[StructuredClone][15](_file, targetRealm, memory_)
到输出的File
对象列表的末尾。返回输出。
在 chrome 中,如果在本地文件系统中为文件设置了只读权限,并且用户在<input type="file">
元素处选择文件,其中FileReader
用于读取文件,则会在FileReader
处引发错误,由FileReader
progress
生成事件。
如果Blob URL
设置为相同的文件对象,则blob:
URL 不会在请求时将只读文件返回给Blob URL
。
在 chrome 中,设置了webkitdirectory
属性并选择具有只读权限的文件夹FileList
.length
of event.target.files
返回0
; event.target.files.webkitGetAsEntry()
未被调用,在<input type="file">
shadowDOM
处呈现"No file chosen"
未"No file chosen"
<input type="file">
。 当文件夹放置在<input type="file">
或放置droppable
属性的元素处时,只读文件夹的目录.name
和.path
显示在drop
event.dataTransfer
。
当用户删除文件或文件夹在<textarea>
元素,在没有drop
附着事件beforeunload
事件被称为和prompr在UI显示
Do you want to leave this site? Changes you made may not be saved. <Stay><Leave> // <buttons>
在火狐版本47.0b9与allowdirs
属性被设置在<input type="file">
元素,其中用户点击"Choose folder.."
<input>
,该文件夹.name
和.path
的父文件夹是在可访问的.then()
链接到event.target.getFilesAndDirectories()
。 递归迭代Directory
条目时,不会返回所选文件夹中包含的文件或文件夹; 返回一个空字符串。
如果用户单击"Choose file..."
<input>
并且选择了一个没有设置只读权限的文件夹,则单击文件管理器中的文件夹时,将列出该文件夹中的文件。
如果选择了设置只读权限的文件夹,则会在 UI 显示时呈现alert()
通知
Could not read the contents of <directory name> Permission denied
*nix 操作系统
当用户在<textarea>
元素放置文件夹时,没有drop
事件附加,用户文件系统file:
协议中file:
夹的完整路径被公开。 文件夹中包含的文件的路径也没有设置为.value
; 例如,
"file:///home/user/Documents/Document/"
当一个文件在丢弃<textarea>
元素,其中不drop
被附加事件,在用户文件系统中的文件的完整路径被设定为.value
的<textarea>
; 也就是说,
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.txt"
如果在<textarea>
元素中选择并放置多个文件,则所有完整文件路径都设置为<textarea>
.value
,以换行符分隔\\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
如果被设置为.src
一个的<img>
与元件.crossOrigin
设置为"anonymous"
的img
error
事件处理程序被调用
在调用window.open()
,在第一个参数中设置了完整路径
Error: Access to '"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.png"' from script denied
4.10.5.1.18。 文件上传状态( type=file
)
由于历史原因,
value
IDL 属性在文件名前加上字符串“C:\\fakepath\\
”。 一些旧的用户代理实际上包含了完整路径(这是一个安全漏洞)。 因此,以向后兼容的方式从value
IDL 属性中获取文件名并非易事。
文件名
获取时,它必须返回字符串 "C:\\fakepath\\" 后跟
selected files
列表中第一个文件的名称(如果有),或者如果列表为空,则返回空字符串。 设置时,如果新值是空字符串,则必须清空selected files
列表; 否则,它必须抛出“InvalidStateError
”DOMException
。注意:这个“fakepath”要求是历史上的一个可悲的意外。 有关更多信息,请参阅文件上传状态部分中的示例。
注意:由于
selected files
列表中的文件名中不允许使用path components
因此不能将“\\fakepath\\
”误认为是路径组件。
4.10.5.1.18。 文件上传状态( type=file
)
当
<input>
元素的type
属性处于File Upload
状态时,本节中的规则适用。
<input>
元素represents
selected files
的列表,每个文件由文件名、文件类型和文件正文(文件内容)组成。文件名不得包含
path components
,即使在用户选择了整个目录层次结构或来自不同目录的多个同名文件的情况下。 出于File Upload
状态的目的,路径组件是文件名中由 U+005C REVERSE SOLIDUS 字符 () 字符分隔的那些部分。
错误报告https://bugzilla.mozilla.org/show_bug.cgi?id=1311823
遵循Neal Deakin在错误报告中的评论
我认为提到的步骤是:
- 打开数据:文本/html,
- 从桌面拖一个文件到textarea
我可以在 Linux 上重现这个,但不能在 Windows 或 Mac 上重现。
上面的预感是正确的; Linux 也将数据作为 url 和纯文本包含在内。
在data:
删除文件data:
firefox 和 chrome、chrome 上的协议data URI
data:text/html,<textarea></textarea>
设置为<textarea>
.value
的文件或文件夹的完整路径名。
在 chrome 上只有textarea
元素的data URI
处删除文件,chrome 在地址栏用删除的文件路径替换data URI
,并在同一选项卡上加载删除的文件,用删除的文件的内容替换data URI
。
plnkr http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview
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
您可以使用附加到#myfile
元素的change
事件来处理用户的文件选择操作。
将<textarea>
元素替换为<p>
元素以显示来自.readAsText()
调用的load
事件的结果。
要显示.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>
FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
文件对象可以从作为用户使用该元素选择文件的结果返回的 FileList 对象、从拖放操作的 DataTransfer 对象或从 HTMLCanvasElement 上的 mozGetAsFile() API 获得。
readAsText方法用于读取指定 Blob 或 File 的内容。 当读操作完成时,readyState 变为 DONE,loadend 被触发,result 属性包含文件内容作为文本字符串。
语法
instanceOfFileReader.readAsText(blob[, encoding]);
参数
斑点
要从中读取的 Blob 或文件。
编码可选
一个字符串,指定用于返回数据的编码。 默认情况下,如果未指定此参数,则假定为 UTF-8。
对于有关文件的元数据,我们可以检查 File 对象F
,以便: F 的可读性状态为 OPENED。 F 指的是 bytes 字节序列。 F.size
设置为以字节为单位的总字节数。 F.name
设置为 n。 F.type
设置为 t。
注意:如果表示 File 对象类型的 ASCII 编码字符串在转换为字节序列时不会为解析 MIME 类型算法 [MIMESNIFF] 返回 undefined,则文件的类型 t 被视为可解析 MIME 类型。
F.lastModified
设置为 d。
在 MDN 上查看更多关于浏览器兼容性和FileReader 、 File和readAsText 的详细文档,以及FileApi 的这个W3C 草案
改用这个:-
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.