javascript - 文件选择器导致 Chrome 冻结
问题描述
我构建了一个组件,允许用户通过单击文件或直接将文件拖放到文件上来上传文件。大多数情况下这工作得很好,但我注意到它会导致谷歌浏览器(版本 94.0.4606.81)经常完全冻结,而不是打开文件选择器。它仍然可以让我按 Ctrl+W 关闭选项卡,但其他选项卡也将保持对鼠标单击无响应。我被迫关闭整个浏览器。但是,我无法在 Microsoft Edge 中重现这一点。
const fileInput = document.querySelector("#fileInput");
const dropArea = document.querySelector("#dropArea");
const upload = document.querySelector("#upload");
function onDragBegin(e) {
e.preventDefault();
e.dataTransfer.dropEffect = "copy";
dropArea.classList.add("dropArea-highlight");
upload.classList.add("upload-highlight");
}
function onDragEnd(e) {
e.preventDefault();
dropArea.classList.remove("dropArea-highlight");
upload.classList.remove("upload-highlight");
}
function onDrop(e) {
fileInput.files = e.dataTransfer.files;
fileInput.dispatchEvent(new Event("change"));
e.preventDefault();
}
async function onChangeFileInput() {
const { files } = this;
dropArea.classList.remove("dropArea-highlight");
upload.classList.remove("upload-highlight");
const url = "/api/har";
const formData = new FormData();
formData.append("harFile", files[0]);
fetch(url, {
method: "POST",
body: formData,
}).then(async (res) => {
if (!res.ok) {
const text = await res.text();
alert(text);
}
if (res.redirected) {
window.location.href = res.url;
}
});
}
dropArea.ondragover = onDragBegin;
dropArea.ondragenter = onDragBegin;
dropArea.ondragleave = onDragEnd;
dropArea.ondrop = onDrop;
fileInput.addEventListener("change", onChangeFileInput);
.upload {
border: 1px dashed var(--copytext-grey);
background-color: #e7eaef;
}
.upload:hover {
background-color: #e1e4ea;
border-style: dotted;
}
.upload-icon {
height: 64px;
filter: invert(36%) sepia(13%) saturate(381%) hue-rotate(171deg)
brightness(93%) contrast(91%);
margin-bottom: 16px;
}
#dropArea {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 4rem 1rem;
}
#dropArea:hover {
cursor: pointer;
}
#dropArea h3 {
color: #555d66;
font-weight: bold;
}
#dropArea p {
color: #676f77;
}
#fileInput {
display: none;
}
.upload-highlight {
background-color: #e1e4ea;
border-style: dotted;
}
.dropArea-highlight {
cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<script src="upload.js" defer></script>
</head>
<body>
<div class="upload" id="upload">
<label for="fileInput">
<div id="dropArea">
<img src="upload.svg" class="upload-icon">
<h3>Drag and drop or click</h3>
<p>to upload your file</p>
<input type="file" name="harFile" id="fileInput" accept=".har">
</div>
</label>
</div>
</body>
</html>
我已经做了一个错误报告,但同时我需要找到一个修复程序来阻止浏览器冻结。如何?
解决方案
鉴于这不是您的代码有问题,因此很难解决该问题。(我的猜测是操作系统无法从中获取元数据的某些注册错误的文件,或者某些网络驱动器(Dropbox、icloud)连接不正确)。
我能想到的唯一解决方法是新的文件系统访问API,希望它不会触发 Chrome 的问题(我认为它们不应该需要相同的元数据)。但是我绝对不确定这是否会发生,所以请告诉我,因为我自己无法重现该问题。
此外,此 API 目前仅在基于 Chromium 的浏览器中受支持,因此您仍然需要<input type=file>
其他浏览器的后备。
由于此 API 在沙盒 iframe 中不可用,因此现场演示存在故障。
// we need to be handling a click event
document.querySelector("button").onclick = async () => {
if( !("showOpenFilePicker" in self) ) {
console.error("unsupported browser, should fallback to <input type=file>");
return;
}
const handles = await showOpenFilePicker();
const file = await handles[0].getFile();
// now you can handle the file as usual
document.getElementById( "log" ).textContent = await file.text();
};
推荐阅读
- react-native - React Native Hooks 在 2 个不同的文件中同步 UseState
- c# - 从客户端应用程序动态调用 Web 服务方法
- bash - 如何在 GNU bash 中使用函数进行算术运算?
- r - 如果第二个字段中的值大于或等于数字(在 R 中),则修改字段中的字符串
- agora.io - 如何使用 Agora Video SDK for Unity 发送纹理
- c++ - C++ 概念能否用于在 C++ 中实现混合类型 min 和 max?
- python - 将列表值与字典的键值进行比较
- loops - PSQL for 循环、连接和分组依据
- git - Jenkins 构建顺序依赖项 SCM
- css - 小圆圈在反应中显示为椭圆