gpt4 book ai didi

javascript - HTML5 File API 中的 FileReader.readAsText 如何工作?

转载 作者:行者123 更新时间:2023-12-04 01:53:50 31 4
gpt4 key购买 nike

我编写了以下代码来使用 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 是否在浏览文件后立即绑定(bind)?

也可以用类似Java的FileReader检查系统Readonly属性是否 File.canread() ?

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

最佳答案

FileReader load事件集 .result异步值。访问 .result使用 loadloadend事件。

当在 <input type="file"> 处选择了文件时Choose FileBrowse... UI,在本地文件系统删除文件应该不会影响 File对象在 FileList返回者 .files称呼。见 2.9.2. Transferable objects , 6.7.3 The DataTransfer interface .

4. The Blob Interface and Binary Data

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 through structured clone. Further normative definition of snapshot state can be found for Files.



2.9.8 Monkey patch for Blob and FileList objects

This monkey patch will be removed in due course. See w3c/FileAPI issue 32.

Blob objects are cloneable objects.

  1. Each Blob object's [[Clone]] internal method, given targetRealm and ignoring memory, must run these steps:

  2. If this is closed, then throw a "DataCloneError" DOMException.

Return a new instance of this in targetRealm, corresponding to the same underlying data.

FileList objects are cloneable objects.

Each FileList object's [[Clone]] internal method, given targetRealm and memory, must run these steps:

  1. Let output be a new FileList object in targetRealm.

  2. For each file in this, add ? [StructuredClone][15](_file, targetRealm, memory_) to the end of the list of File objects of output.

Return output.



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

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

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

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

Chrome 、 Chrome

在 Chrome , Chrome 哪里 webkitdirectory设置属性并选择具有只读权限的文件夹 FileList .lengthevent.target.files返回 0 ; event.target.files.webkitGetAsEntry()不叫, "No file chosen"呈现在 <input type="file"> shadowDOM .当文件夹被放置在 <input type="file">或元素 where droppable属性集,目录 .name.path只读文件夹的目录显示在 drop event.dataTransfer .

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

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


火狐

在 firefox 版本 47.0b9 上使用 allowdirs属性设置为 <input type="file">元素,用户单击的位置 "Choose folder.." <input> , 文件夹 .name.path可以在 .then() 访问父文件夹的链接到 event.target.getFilesAndDirectories() .递归迭代 Directory时不返回所选文件夹中包含的文件或文件夹条目;返回一个空字符串。

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

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

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


错误、安全问题

*nix 操作系统

当用户在 <textarea> 放置文件夹时元素,其中没有 drop事件已附加,用户文件系统中文件夹的完整路径 file:协议(protocol)暴露。文件夹中包含的文件的路径也未设置为 .value ;例如。,
"file:///home/user/Documents/Document/"

当文件被放置在 <textarea>元素,如果不是 drop附加事件,用户文件系统中文件的完整路径设置为 .value<textarea> ;那是,
"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

当设置为 .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. File Upload state ( type=file )

EXAMPLE 16

For historical reasons, the value IDL attribute prefixes the file name with the string "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.



4.10.5.4. Common <input> element APIs

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. On setting, if the new value is the empty string, it must empty the list of selected files; otherwise, it must throw an "InvalidStateError" DOMException.

NOTE: This "fakepath" requirement is a sad accident of history. 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 of selected files, the "\fakepath\" cannot be mistaken for a path component.




4.10.5.1.18. File Upload state ( type=file )

路径组件

When an <input> element’s type attribute is in the File Upload state, the rules in this section apply.

The <input> element represents a list of selected files, each file consisting of a file name, a file type, and a file body (the contents of the file).

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, for the purposes of the File Upload state, are those parts of file names that are separated by U+005C REVERSE SOLIDUS character () characters.



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

在数据 URI 的 <textarea> 处删除文件

以下评论来自 Neal Deakin在错误报告

I think the steps referred to are:

  1. Open data:text/html,
  2. Drag a file from the desktop to the textarea

I can reproduce this on Linux, but not on Windows or Mac.

The hunch above is correct; Linux is including the data as a url and plaintext as well.



data: 删除文件协议(protocol) data URI在 Firefox 和 Chrome 、 Chrome
data:text/html,<textarea></textarea>

火狐

文件或文件夹的全路径名设置为 .value<textarea> .

Chrome 、 Chrome

data URI 删除文件只有 textarea Chrome 元素, 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

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

替代 <textarea> <p> 的元素显示 load 结果的元素事件来自 .readAsText()称呼。

显示 .resultFileReaderclickbutton元素,设置变量 textreader.resultload 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>

关于javascript - HTML5 File API 中的 FileReader.readAsText 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40146768/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com